Skip to content

Commit 89759b6

Browse files
HG-hafoxxorcat
andauthored
fix(lanzou): support acw_sc__v2 and secondary validation for download link (#1379)
* 重定向链接添加acw_sc__v2验证 在最新的蓝奏云解析中,最后重定向获取真实地址时也需要添加acw_sc__v2信息 Signed-off-by: HG-ha <[email protected]> * 重定向链接添加acw_sc__v2验证 Signed-off-by: HG-ha <[email protected]> * 重定向真实下载链接添加acw_sc__v2验证 Signed-off-by: HG-ha <[email protected]> * fix: CalcAcwScV2 * Add error handling for response body read Handle error when reading response body. Signed-off-by: HG-ha <[email protected]> * Improve response handling and validation logic 优化重定向资源管理,添加二次人机验证acw_sc__v2处理 Signed-off-by: HG-ha <[email protected]> --------- Signed-off-by: HG-ha <[email protected]> Co-authored-by: foxxorcat <[email protected]>
1 parent a2fc38b commit 89759b6

File tree

2 files changed

+103
-27
lines changed

2 files changed

+103
-27
lines changed

drivers/lanzou/help.go

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package lanzou
22

33
import (
4-
"bytes"
4+
"encoding/hex"
5+
"errors"
56
"fmt"
67
"net/http"
78
"regexp"
89
"strconv"
910
"strings"
1011
"time"
1112
"unicode"
12-
13-
log "github.com/sirupsen/logrus"
1413
)
1514

1615
const DAY time.Duration = 84600000000000
@@ -122,35 +121,48 @@ var findAcwScV2Reg = regexp.MustCompile(`arg1='([0-9A-Z]+)'`)
122121

123122
// 在页面被过多访问或其他情况下,有时候会先返回一个加密的页面,其执行计算出一个acw_sc__v2后放入页面后再重新访问页面才能获得正常页面
124123
// 若该页面进行了js加密,则进行解密,计算acw_sc__v2,并加入cookie
125-
func CalcAcwScV2(html string) (string, error) {
126-
log.Debugln("acw_sc__v2", html)
127-
acwScV2s := findAcwScV2Reg.FindStringSubmatch(html)
128-
if len(acwScV2s) != 2 {
129-
return "", fmt.Errorf("无法匹配acw_sc__v2")
124+
func CalcAcwScV2(htmlContent string) (string, error) {
125+
matches := findAcwScV2Reg.FindStringSubmatch(htmlContent)
126+
if len(matches) != 2 {
127+
return "", errors.New("无法匹配到 arg1 参数")
130128
}
131-
return HexXor(Unbox(acwScV2s[1]), "3000176000856006061501533003690027800375"), nil
129+
arg1 := matches[1]
130+
131+
mask := "3000176000856006061501533003690027800375"
132+
result, err := hexXor(unbox(arg1), mask)
133+
if err != nil {
134+
return "", fmt.Errorf("hexXor 操作失败: %w", err)
135+
}
136+
137+
return result, nil
132138
}
133139

134-
func Unbox(hex string) string {
140+
func unbox(hex string) string {
135141
var box = []int{6, 28, 34, 31, 33, 18, 30, 23, 9, 8, 19, 38, 17, 24, 0, 5, 32, 21, 10, 22, 25, 14, 15, 3, 16, 27, 13, 35, 2, 29, 11, 26, 4, 36, 1, 39, 37, 7, 20, 12}
136142
var newBox = make([]byte, len(hex))
137-
for i := 0; i < len(box); i++ {
138-
j := box[i]
143+
for i, j := range box {
139144
if len(newBox) > j {
140145
newBox[j] = hex[i]
141146
}
142147
}
143148
return string(newBox)
144149
}
145150

146-
func HexXor(hex1, hex2 string) string {
147-
out := bytes.NewBuffer(make([]byte, len(hex1)))
148-
for i := 0; i < len(hex1) && i < len(hex2); i += 2 {
149-
v1, _ := strconv.ParseInt(hex1[i:i+2], 16, 64)
150-
v2, _ := strconv.ParseInt(hex2[i:i+2], 16, 64)
151-
out.WriteString(strconv.FormatInt(v1^v2, 16))
151+
func hexXor(hex1, hex2 string) (string, error) {
152+
bytes1, err := hex.DecodeString(hex1)
153+
if err != nil {
154+
return "", fmt.Errorf("解码 hex1 失败: %w", err)
155+
}
156+
bytes2, err := hex.DecodeString(hex2)
157+
if err != nil {
158+
return "", fmt.Errorf("解码 hex2 失败: %w", err)
159+
}
160+
minLength := min(len(bytes2), len(bytes1))
161+
resultBytes := make([]byte, minLength)
162+
for i := range minLength {
163+
resultBytes[i] = bytes1[i] ^ bytes2[i]
152164
}
153-
return out.String()
165+
return hex.EncodeToString(resultBytes), nil
154166
}
155167

156168
var findDataReg = regexp.MustCompile(`data[:\s]+({[^}]+})`) // 查找json

drivers/lanzou/util.go

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lanzou
33
import (
44
"errors"
55
"fmt"
6+
"io"
67
"net/http"
78
"regexp"
89
"runtime"
@@ -430,27 +431,90 @@ func (d *LanZou) getFilesByShareUrl(shareID, pwd string, sharePageData string) (
430431
file.Time = timeFindReg.FindString(sharePageData)
431432

432433
// 重定向获取真实链接
433-
res, err := base.NoRedirectClient.R().SetHeaders(map[string]string{
434-
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
435-
}).Get(downloadUrl)
434+
var (
435+
res *resty.Response
436+
err error
437+
)
438+
var vs string
439+
var bodyStr string
440+
for i := 0; i < 3; i++ {
441+
res, err = base.NoRedirectClient.R().SetHeaders(map[string]string{
442+
"accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
443+
"Referer": baseUrl,
444+
}).SetDoNotParseResponse(true).
445+
SetCookie(&http.Cookie{
446+
Name: "acw_sc__v2",
447+
Value: vs,
448+
}).Get(downloadUrl)
449+
if err != nil {
450+
return nil, err
451+
}
452+
453+
if res.StatusCode() == 302 {
454+
if res.RawBody() != nil {
455+
res.RawBody().Close()
456+
}
457+
break
458+
}
459+
bodyBytes, err := io.ReadAll(res.RawBody())
460+
if res.RawBody() != nil {
461+
res.RawBody().Close()
462+
}
463+
if err != nil {
464+
return nil, fmt.Errorf("读取响应体失败: %w", err)
465+
}
466+
bodyStr = string(bodyBytes)
467+
if strings.Contains(bodyStr, "acw_sc__v2") {
468+
if vs, err = CalcAcwScV2(bodyStr); err != nil {
469+
log.Errorf("lanzou: err => acw_sc__v2 validation error ,data => %s\n", bodyStr)
470+
return nil, err
471+
}
472+
continue
473+
}
474+
break
475+
}
476+
436477
if err != nil {
437478
return nil, err
438479
}
439480

440481
file.Url = res.Header().Get("location")
441482

442-
// 触发验证
443-
rPageData := res.String()
483+
// 触发二次验证,也需要处理一下触发acw_sc__v2的情况
444484
if res.StatusCode() != 302 {
445-
param, err = htmlJsonToMap(rPageData)
485+
param, err = htmlJsonToMap(bodyStr)
446486
if err != nil {
447487
return nil, err
448488
}
449489
param["el"] = "2"
450490
time.Sleep(time.Second * 2)
451491

452-
// 通过验证获取直连
453-
data, err := d.post(fmt.Sprint(baseUrl, "/ajax.php"), func(req *resty.Request) { req.SetFormData(param) }, nil)
492+
// 通过验证获取直链
493+
var data []byte
494+
for i := 0; i < 3; i++ {
495+
data, err = d.post(fmt.Sprint(baseUrl, "/ajax.php"), func(req *resty.Request) {
496+
req.SetFormData(param)
497+
if vs != "" {
498+
req.SetCookie(&http.Cookie{
499+
Name: "acw_sc__v2",
500+
Value: vs,
501+
})
502+
}
503+
}, nil)
504+
if err != nil {
505+
return nil, err
506+
}
507+
ajaxBodyStr := string(data)
508+
if strings.Contains(ajaxBodyStr, "acw_sc__v2") {
509+
if vs, err = CalcAcwScV2(ajaxBodyStr); err != nil {
510+
log.Errorf("lanzou: err => acw_sc__v2 validation error ,data => %s\n", ajaxBodyStr)
511+
return nil, err
512+
}
513+
time.Sleep(time.Second * 2)
514+
continue
515+
}
516+
break
517+
}
454518
if err != nil {
455519
return nil, err
456520
}

0 commit comments

Comments
 (0)