fix(iLanZou): resolve resource access issue (#6673)

* fix(drivers/iLanZou): resolve resource access issue on iLanZou driver mount

The driver failed to mount due to incorrect URL parameter ordering which the backend did not accept

This commit reorders the parameters to meet the backend's expectations

and ensures successful mounting of the iLanZou driver.

Closes #6271, Closes #6415

* fix(drivers/iLanZou): Fixed the error ID number returned when creating a folder

Closes #6610, Closes #6333

---------

Co-authored-by: maye174 <96584640+maye174@users.noreply.github.com>
This commit is contained in:
lany 2024-07-02 15:30:00 +08:00 committed by GitHub
parent 432901db5a
commit 2705877235
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 57 deletions

View File

@ -66,18 +66,18 @@ func (d *ILanZou) Drop(ctx context.Context) error {
} }
func (d *ILanZou) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) { func (d *ILanZou) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
offset := 1
limit := 60
var res []ListItem var res []ListItem
for { for {
var resp ListResp var resp ListResp
_, err := d.proved("/record/file/list", http.MethodGet, func(req *resty.Request) { _, err := d.proved("/record/file/list", http.MethodGet, func(req *resty.Request) {
req.SetQueryParams(map[string]string{ params := []string{
"type": "0", "offset=1",
"folderId": dir.GetID(), "limit=60",
"offset": strconv.Itoa(offset), "folderId=" + dir.GetID(),
"limit": strconv.Itoa(limit), "type=0",
}).SetResult(&resp) }
queryString := strings.Join(params, "&")
req.SetQueryString(queryString).SetResult(&resp)
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -86,7 +86,6 @@ func (d *ILanZou) List(ctx context.Context, dir model.Obj, args model.ListArgs)
if resp.TotalPage <= resp.Offset { if resp.TotalPage <= resp.Offset {
break break
} }
offset++
} }
return utils.SliceConvert(res, func(f ListItem) (model.Obj, error) { return utils.SliceConvert(res, func(f ListItem) (model.Obj, error) {
updTime, err := time.ParseInLocation("2006-01-02 15:04:05", f.UpdTime, time.Local) updTime, err := time.ParseInLocation("2006-01-02 15:04:05", f.UpdTime, time.Local)
@ -118,31 +117,33 @@ func (d *ILanZou) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
query := u.Query() ts, ts_str, err := getTimestamp(d.conf.secret)
query.Set("uuid", d.UUID)
query.Set("devType", "6") params := []string{
query.Set("devCode", d.UUID) "uuid=" + url.QueryEscape(d.UUID),
query.Set("devModel", "chrome") "devType=6",
query.Set("devVersion", d.conf.devVersion) "devCode=" + url.QueryEscape(d.UUID),
query.Set("appVersion", "") "devModel=chrome",
ts, err := getTimestamp(d.conf.secret) "devVersion=" + url.QueryEscape(d.conf.devVersion),
if err != nil { "appVersion=",
return nil, err "timestamp=" + ts_str,
"appToken=" + url.QueryEscape(d.Token),
"enable=0",
} }
query.Set("timestamp", ts)
query.Set("appToken", d.Token)
query.Set("enable", "1")
downloadId, err := mopan.AesEncrypt([]byte(fmt.Sprintf("%s|%s", file.GetID(), d.userID)), d.conf.secret) downloadId, err := mopan.AesEncrypt([]byte(fmt.Sprintf("%s|%s", file.GetID(), d.userID)), d.conf.secret)
if err != nil { if err != nil {
return nil, err return nil, err
} }
query.Set("downloadId", hex.EncodeToString(downloadId)) params = append(params, "downloadId="+url.QueryEscape(hex.EncodeToString(downloadId)))
auth, err := mopan.AesEncrypt([]byte(fmt.Sprintf("%s|%d", file.GetID(), time.Now().UnixMilli())), d.conf.secret)
auth, err := mopan.AesEncrypt([]byte(fmt.Sprintf("%s|%d", file.GetID(), ts)), d.conf.secret)
if err != nil { if err != nil {
return nil, err return nil, err
} }
query.Set("auth", hex.EncodeToString(auth)) params = append(params, "auth="+url.QueryEscape(hex.EncodeToString(auth)))
u.RawQuery = query.Encode()
u.RawQuery = strings.Join(params, "&")
realURL := u.String() realURL := u.String()
// get the url after redirect // get the url after redirect
res, err := base.NoRedirectClient.R().SetHeaders(map[string]string{ res, err := base.NoRedirectClient.R().SetHeaders(map[string]string{
@ -156,12 +157,7 @@ func (d *ILanZou) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
if res.StatusCode() == 302 { if res.StatusCode() == 302 {
realURL = res.Header().Get("location") realURL = res.Header().Get("location")
} else { } else {
contentLengthStr := res.Header().Get("Content-Length") return nil, fmt.Errorf("redirect failed, status: %d, msg: %s", res.StatusCode(), utils.Json.Get(res.Body(), "msg").ToString())
contentLength, err := strconv.Atoi(contentLengthStr)
if err != nil || contentLength == 0 || contentLength > 1024*10 {
return nil, fmt.Errorf("redirect failed, status: %d", res.StatusCode())
}
return nil, fmt.Errorf("redirect failed, content: %s", res.String())
} }
link := model.Link{URL: realURL} link := model.Link{URL: realURL}
return &link, nil return &link, nil
@ -179,7 +175,7 @@ func (d *ILanZou) MakeDir(ctx context.Context, parentDir model.Obj, dirName stri
return nil, err return nil, err
} }
return &model.Object{ return &model.Object{
ID: utils.Json.Get(res, "list", "0", "id").ToString(), ID: utils.Json.Get(res, "list", 0, "id").ToString(),
//Path: "", //Path: "",
Name: dirName, Name: dirName,
Size: 0, Size: 0,
@ -348,10 +344,12 @@ func (d *ILanZou) Put(ctx context.Context, dstDir model.Obj, stream model.FileSt
var resp UploadResultResp var resp UploadResultResp
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
_, err = d.unproved("/7n/results", http.MethodPost, func(req *resty.Request) { _, err = d.unproved("/7n/results", http.MethodPost, func(req *resty.Request) {
req.SetQueryParams(map[string]string{ params := []string{
"tokenList": token, "tokenList=" + token,
"tokenTime": time.Now().Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"), "tokenTime=" + time.Now().Format("Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"),
}).SetResult(&resp) }
queryString := strings.Join(params, "&")
req.SetQueryString(queryString).SetResult(&resp)
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -4,7 +4,9 @@ import (
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"net/http" "net/http"
"net/url"
"strconv" "strconv"
"strings"
"time" "time"
"github.com/alist-org/alist/v3/drivers/base" "github.com/alist-org/alist/v3/drivers/base"
@ -31,45 +33,52 @@ func (d *ILanZou) login() error {
return nil return nil
} }
func getTimestamp(secret []byte) (string, error) { func getTimestamp(secret []byte) (int64, string, error) {
ts := time.Now().UnixMilli() ts := time.Now().UnixMilli()
tsStr := strconv.FormatInt(ts, 10) tsStr := strconv.FormatInt(ts, 10)
res, err := mopan.AesEncrypt([]byte(tsStr), secret) res, err := mopan.AesEncrypt([]byte(tsStr), secret)
if err != nil { if err != nil {
return "", err return 0, "", err
} }
return hex.EncodeToString(res), nil return ts, hex.EncodeToString(res), nil
} }
func (d *ILanZou) request(pathname, method string, callback base.ReqCallback, proved bool, retry ...bool) ([]byte, error) { func (d *ILanZou) request(pathname, method string, callback base.ReqCallback, proved bool, retry ...bool) ([]byte, error) {
req := base.RestyClient.R() _, ts_str, err := getTimestamp(d.conf.secret)
ts, err := getTimestamp(d.conf.secret)
if err != nil { if err != nil {
return nil, err return nil, err
} }
req.SetQueryParams(map[string]string{
"uuid": d.UUID, params := []string{
"devType": "6", "uuid=" + url.QueryEscape(d.UUID),
"devCode": d.UUID, "devType=6",
"devModel": "chrome", "devCode=" + url.QueryEscape(d.UUID),
"devVersion": d.conf.devVersion, "devModel=chrome",
"appVersion": "", "devVersion=" + url.QueryEscape(d.conf.devVersion),
"timestamp": ts, "appVersion=",
//"appToken": d.Token, "timestamp=" + ts_str,
"extra": "2", }
})
if proved {
params = append(params, "appToken="+url.QueryEscape(d.Token))
}
params = append(params, "extra=2")
queryString := strings.Join(params, "&")
req := base.RestyClient.R()
req.SetHeaders(map[string]string{ req.SetHeaders(map[string]string{
"Origin": d.conf.site, "Origin": d.conf.site,
"Referer": d.conf.site + "/", "Referer": d.conf.site + "/",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0", "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
}) })
if proved {
req.SetQueryParam("appToken", d.Token)
}
if callback != nil { if callback != nil {
callback(req) callback(req)
} }
res, err := req.Execute(method, d.conf.base+pathname)
res, err := req.Execute(method, d.conf.base+pathname+"?"+queryString)
if err != nil { if err != nil {
if res != nil { if res != nil {
log.Errorf("[iLanZou] request error: %s", res.String()) log.Errorf("[iLanZou] request error: %s", res.String())