Skip to content

Commit

Permalink
feat(vpn-qr-code): generate qr code via its content directly, instead…
Browse files Browse the repository at this point in the history
… of requsting qr image

The content of the qr code is a url of `https://sis.ustb.edu.cn/connect/state?sid=${SID}`,
we can generate the qr code via the parsed ${SID}. Then the http request of the qr image
can be omitted.
  • Loading branch information
genshen committed Jun 9, 2024
1 parent c293472 commit 3103aff
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 16 deletions.
14 changes: 4 additions & 10 deletions client-ui/qr_login_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,18 @@ package main

import (
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/storage"
"github.com/genshen/wssocks-plugin-ustb/plugins/vpn"
log "github.com/sirupsen/logrus"
)

// LoadQRImage shows QR image for login
func LoadQRImage() *canvas.Image {
if qrCodeImgUrl, err := vpn.ParseQRCodeImgUrl(); err != nil {
if qrImgReader, err := vpn.LoadQrAuthImage(); err != nil {
log.Println(err) // todo
return nil
} else {
if uri, err := storage.ParseURI(qrCodeImgUrl); err != nil {
log.Println(err) // todo:
return nil
} else {
image := canvas.NewImageFromURI(uri)
image.FillMode = canvas.ImageFillOriginal
return image
}
image := canvas.NewImageFromReader(qrImgReader, "qr.png")
image.FillMode = canvas.ImageFillOriginal
return image
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/genshen/cmds v0.0.0-20200505065256-d4c52690e15b
github.com/genshen/wssocks v0.6.1
github.com/sirupsen/logrus v1.9.3
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
golang.org/x/crypto v0.18.0
gopkg.in/yaml.v3 v3.0.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJV
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
Expand Down
52 changes: 46 additions & 6 deletions plugins/vpn/qr_code.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import (
"bytes"
"errors"
"fmt"
"github.com/skip2/go-qrcode"
"gopkg.in/yaml.v3"
"io"
"net/http"
"net/url"
"strings"
)

const LoadImgUrl = "https://n.ustb.edu.cn/login/"
const SisAuthPath = "https://sis.ustb.edu.cn"
const FindQrcodeUrlRegex = `"ustb-qrcode",`
const FindQrcodeImgTagRegex = `<img`

Expand Down Expand Up @@ -43,9 +46,16 @@ func (q *QRCodeImgLoaderConfig) genIframeUrl() (string, error) {
return fmt.Sprintf("%s?appid=%s&return_url=%s&rand_token=%s&embed_flag=1", q.ApiUrl, q.AppID, q.ReturnUrl, q.RandToken), nil
}

type QrImg struct {
imgUrl string
QrImg []byte
Sid string // sis in ustb auth, can be parsed from image url.
}

// ParseQRCodeImgUrl uses ParseQRCodeHtmlUrl to get the iframe html,
// and then parse the html file to get final image url (contains SID)
func ParseQRCodeImgUrl() (string, error) {
// and then parse the html file to get final image url (contains SID).
// And set QrImg's imgUrl and sid.
func (i *QrImg) ParseQRCodeImgUrl() (string, error) {
iframeUrl, err := ParseQRCodeHtmlUrl()
if err != nil {
return "", err
Expand All @@ -64,7 +74,6 @@ func ParseQRCodeImgUrl() (string, error) {
defer response.Body.Close()

scanner := bufio.NewScanner(response.Body)
imgUrl := ""
for scanner.Scan() {
line := scanner.Text()
if strings.Contains(line, FindQrcodeImgTagRegex) { // first line to match start
Expand All @@ -73,7 +82,7 @@ func ParseQRCodeImgUrl() (string, error) {
if len(subStr) != 5 {
return "", errors.New("invalid format in qr image url parsing")
} else {
imgUrl = subStr[3]
i.imgUrl = subStr[3]
break
}
}
Expand All @@ -83,8 +92,16 @@ func ParseQRCodeImgUrl() (string, error) {
return "", err
}

// parse sid in qr image url.
sidStr := strings.SplitN(i.imgUrl, "=", 2)
if len(sidStr) != 2 {
return "", errors.New("invalid format in qr image url (sis) parsing")
} else {
i.Sid = sidStr[1]
}

// use htmlUri's host, schema
return fmt.Sprintf("%s://%s%s", htmlUri.Scheme, htmlUri.Host, imgUrl), nil
return fmt.Sprintf("%s://%s%s", htmlUri.Scheme, htmlUri.Host, i.imgUrl), nil
}

func ParseQRCodeHtmlUrl() (string, error) {
Expand Down Expand Up @@ -140,7 +157,30 @@ func ParseQRCodeHtmlUrl() (string, error) {
}
}

// wait qr state and get auth code
func (i *QrImg) GenQrImg() error {
imgContent := fmt.Sprintf(SisAuthPath+"/auth?sid=%s", i.Sid)
qrPng, err := qrcode.Encode(imgContent, qrcode.Medium, 256)
if err != nil {
return err
}
i.QrImg = qrPng
return nil
}

func LoadQrAuthImage() (io.Reader, error) {
var qr QrImg
if _, err := qr.ParseQRCodeImgUrl(); err != nil {
return nil, err
}

if err := qr.GenQrImg(); err != nil {
return nil, err
}
buf := bytes.NewReader(qr.QrImg)
return buf, nil
}

// WaitQrState waits qr state and get auth code
func WaitQrState(imgUrl *url.URL) {
// get https://sis.ustb.edu.cn/connect/state?sid=bf1a027b75d6e21b351f81cdc1b739a2
}

0 comments on commit 3103aff

Please sign in to comment.