chore: Merge pull request #872 from Xhofe/dev

fix quark cookie, virtual path
This commit is contained in:
Xhofe 2022-03-31 20:58:56 +08:00 committed by GitHub
commit 948bbe9136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 315 additions and 149 deletions

View File

@ -86,4 +86,4 @@ The `AList` is open-source software licensed under the AGPL-3.0 license.
---
> [@Blog](https://www.nn.ci/) · [@GitHub](https://github.com/Xhofe) · [@TelegramGroup](https://t.me/alist_chat) · [@QQGroup](https://jq.qq.com/?_wv=1027&k=OVPJcv2b)
> [@Blog](https://nn.ci/) · [@GitHub](https://github.com/Xhofe) · [@TelegramGroup](https://t.me/alist_chat) · [@QQGroup](https://jq.qq.com/?_wv=1027&k=OVPJcv2b)

View File

@ -86,4 +86,4 @@
---
> [@Blog](https://www.nn.ci/) · [@GitHub](https://github.com/Xhofe) · [@TelegramGroup](https://t.me/alist_chat) · [@QQGroup](https://jq.qq.com/?_wv=1027&k=OVPJcv2b)
> [@Blog](https://nn.ci/) · [@GitHub](https://github.com/Xhofe) · [@TelegramGroup](https://t.me/alist_chat) · [@QQGroup](https://jq.qq.com/?_wv=1027&k=OVPJcv2b)

View File

@ -3,6 +3,7 @@ package bootstrap
import (
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/drivers/operate"
"github.com/Xhofe/alist/model"
log "github.com/sirupsen/logrus"
)
@ -20,7 +21,8 @@ func InitAccounts() {
log.Errorf("no [%s] driver", account.Type)
} else {
log.Infof("start init account: [%s], type: [%s]", account.Name, account.Type)
err := driver.Save(&accounts[i], nil)
//err := driver.Save(&accounts[i], nil)
err := operate.Save(driver, &accounts[i], nil)
if err != nil {
log.Errorf("init account [%s] error:[%s]", account.Name, err.Error())
} else {

View File

@ -228,7 +228,7 @@ func (driver AliDrive) batch(srcId, dstId string, url string, account *model.Acc
}
return fmt.Errorf("%s", e.Message)
}
status := jsoniter.Get(res.Body(), "status").ToInt()
status := jsoniter.Get(res.Body(), "responses", 0, "status").ToInt()
if status < 400 && status >= 100 {
return nil
}

View File

@ -94,15 +94,15 @@ func (driver AliDrive) Save(account *model.Account, old *model.Account) error {
log.Debugf("user info: %+v", resp)
account.DriveId = resp["default_drive_id"].(string)
cronId, err := conf.Cron.AddFunc("@every 2h", func() {
name := account.Name
log.Debugf("ali account name: %s", name)
newAccount, ok := model.GetAccount(name)
id := account.ID
log.Debugf("ali account id: %d", id)
newAccount, err := model.GetAccountById(id)
log.Debugf("ali account: %+v", newAccount)
if !ok {
if err != nil {
return
}
err = driver.RefreshToken(&newAccount)
_ = model.SaveAccount(&newAccount)
err = driver.RefreshToken(newAccount)
_ = model.SaveAccount(newAccount)
})
if err != nil {
return err

View File

@ -8,6 +8,10 @@ import (
"runtime/debug"
)
func Save(driver base.Driver, account, old *model.Account) error {
return driver.Save(account, old)
}
func Path(driver base.Driver, account *model.Account, path string) (*model.File, []model.File, error) {
return driver.Path(path, account)
}

View File

@ -64,6 +64,12 @@ func (driver Quark) Save(account *model.Account, old *model.Account) error {
return nil
}
_, err := driver.Get("/config", nil, nil, account)
if err == nil {
account.Status = "work"
} else {
account.Status = err.Error()
}
_ = model.SaveAccount(account)
return err
}

View File

@ -8,6 +8,7 @@ import (
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/utils"
"github.com/Xhofe/alist/utils/cookie"
"github.com/go-resty/resty/v2"
log "github.com/sirupsen/logrus"
"net/http"
@ -62,7 +63,12 @@ func (driver Quark) Request(pathname string, method int, headers, query, form ma
if err != nil {
return nil, err
}
log.Debugf("%s response: %s", pathname, res.String())
__puus := cookie.GetCookie(res.Cookies(), "__puus")
if __puus != nil {
account.AccessToken = cookie.SetStr(account.AccessToken, "__puus", __puus.Value)
_ = model.SaveAccount(account)
}
//log.Debugf("%s response: %s", pathname, res.String())
if e.Status >= 400 || e.Code != 0 {
return nil, errors.New(e.Message)
}

View File

@ -1,6 +1,7 @@
package s3
import (
"bytes"
"fmt"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/drivers/base"
@ -9,6 +10,7 @@ import (
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/url"
"path/filepath"
"time"
@ -78,6 +80,7 @@ func (driver S3) Items() []base.Item {
Label: "placeholder filename",
Type: base.TypeString,
Description: "default empty string",
Default: defaultPlaceholderName,
},
{
Name: "bool_1",
@ -213,8 +216,19 @@ func (driver S3) Preview(path string, account *model.Account) (interface{}, erro
}
func (driver S3) MakeDir(path string, account *model.Account) error {
// not support, default as success
return nil
// not support, generate a placeholder file
_, err := driver.File(path, account)
// exist
if err != base.ErrPathNotFound {
return nil
}
return driver.Upload(&model.FileStream{
File: ioutil.NopCloser(bytes.NewReader([]byte{})),
Size: 0,
ParentPath: path,
Name: getPlaceholderName(account.Zone),
MIMEType: "application/octet-stream",
}, account)
}
func (driver S3) Move(src string, dst string, account *model.Account) error {
@ -277,6 +291,7 @@ func (driver S3) Upload(file *model.FileStream, account *model.Account) error {
}
uploader := s3manager.NewUploader(s)
key := driver.GetKey(utils.Join(file.ParentPath, file.GetFileName()), account, false)
log.Debugln("key:", key)
input := &s3manager.UploadInput{
Bucket: &account.Bucket,
Key: &key,

View File

@ -88,7 +88,7 @@ func (driver S3) List(prefix string, account *model.Account) ([]model.File, erro
}
for _, object := range listObjectsResult.Contents {
name := utils.Base(*object.Key)
if name == account.Zone {
if name == getPlaceholderName(account.Zone) {
continue
}
file := model.File{
@ -152,7 +152,7 @@ func (driver S3) ListV2(prefix string, account *model.Account) ([]model.File, er
}
for _, object := range listObjectsResult.Contents {
name := utils.Base(*object.Key)
if name == account.Zone {
if name == getPlaceholderName(account.Zone) {
continue
}
file := model.File{

10
drivers/s3/util.go Normal file
View File

@ -0,0 +1,10 @@
package s3
var defaultPlaceholderName = ".placeholder"
func getPlaceholderName(placeholder string) string {
if placeholder == "" {
return defaultPlaceholderName
}
return placeholder
}

View File

@ -13,7 +13,7 @@ import (
log "github.com/sirupsen/logrus"
)
var xunleiClient = resty.New().SetHeaders(map[string]string{"Accept": "application/json;charset=UTF-8"})
var xunleiClient = resty.New().SetHeaders(map[string]string{"Accept": "application/json;charset=UTF-8"}).SetTimeout(base.DefaultTimeout)
// 一个账户只允许登陆一次
var userStateCache = struct {

View File

@ -2,6 +2,7 @@ package model
import (
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/utils"
log "github.com/sirupsen/logrus"
"strings"
"sync"
@ -97,6 +98,7 @@ func RegisterAccount(account Account) {
accountsMap[account.Name] = account
}
// GetAccount 根据名称获取账号(不包含负载均衡账号) 用于定时任务更新账号
func GetAccount(name string) (Account, bool) {
if len(accountsMap) == 1 {
for _, v := range accountsMap {
@ -107,25 +109,28 @@ func GetAccount(name string) (Account, bool) {
return account, ok
}
func GetAccountsByName(name string) []Account {
accounts := make([]Account, 0)
if AccountsCount() == 1 {
account, _ := GetAccount("")
accounts = append(accounts, account)
return accounts
}
for _, v := range accountsMap {
if v.Name == name || strings.HasPrefix(v.Name, name+balance) {
accounts = append(accounts, v)
}
}
return accounts
}
// GetAccountsByName 根据名称获取账号(包含负载均衡账号)
//func GetAccountsByName(name string) []Account {
// accounts := make([]Account, 0)
// if AccountsCount() == 1 {
// for _, v := range accountsMap {
// accounts = append(accounts, v)
// }
// return accounts
// }
// for _, v := range accountsMap {
// if v.Name == name || strings.HasPrefix(v.Name, name+balance) {
// accounts = append(accounts, v)
// }
// }
// return accounts
//}
var balanceMap sync.Map
// GetBalancedAccount 根据名称获取账号,负载均衡之后的
func GetBalancedAccount(name string) (Account, bool) {
accounts := GetAccountsByName(name)
accounts := GetAccountsByPath(name)
accountNum := len(accounts)
switch accountNum {
case 0:
@ -147,6 +152,7 @@ func GetBalancedAccount(name string) (Account, bool) {
}
}
// GetAccountById 根据id获取账号用于更新账号
func GetAccountById(id uint) (*Account, error) {
var account Account
account.ID = id
@ -156,27 +162,29 @@ func GetAccountById(id uint) (*Account, error) {
return &account, nil
}
func GetAccountFiles() ([]File, error) {
files := make([]File, 0)
var accounts []Account
if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
return nil, err
}
for _, v := range accounts {
if strings.Contains(v.Name, balance) {
continue
}
files = append(files, File{
Name: v.Name,
Size: 0,
Driver: v.Type,
Type: conf.FOLDER,
UpdatedAt: v.UpdatedAt,
})
}
return files, nil
}
// GetAccountFiles 获取账号虚拟文件(去除负载均衡)
//func GetAccountFiles() ([]File, error) {
// files := make([]File, 0)
// var accounts []Account
// if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
// return nil, err
// }
// for _, v := range accounts {
// if strings.Contains(v.Name, balance) {
// continue
// }
// files = append(files, File{
// Name: v.Name,
// Size: 0,
// Driver: v.Type,
// Type: conf.FOLDER,
// UpdatedAt: v.UpdatedAt,
// })
// }
// return files, nil
//}
// GetAccounts 获取所有账号
func GetAccounts() ([]Account, error) {
var accounts []Account
if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
@ -184,3 +192,70 @@ func GetAccounts() ([]Account, error) {
}
return accounts, nil
}
// GetAccountsByPath 根据路径获取账号,最长匹配,未负载均衡
// 如有账号: /a/b,/a/c,/a/d/e,/a/d/e.balance
// GetAccountsByPath(/a/d/e/f) => /a/d/e,/a/d/e.balance
func GetAccountsByPath(path string) []Account {
accounts := make([]Account, 0)
curSlashCount := 0
for _, v := range accountsMap {
name := utils.ParsePath(v.Name)
bIndex := strings.LastIndex(name, balance)
if bIndex != -1 {
name = v.Name[:bIndex]
}
// 不是这个账号
if path != name && !strings.HasPrefix(path, name+"/") {
continue
}
slashCount := strings.Count(name, "/")
// 不是最长匹配
if slashCount < curSlashCount {
continue
}
if slashCount > curSlashCount {
accounts = accounts[:0]
curSlashCount = slashCount
}
accounts = append(accounts, v)
}
return accounts
}
// GetAccountFilesByPath 根据路径获取账号虚拟文件
// 如有账号: /a/b,/a/c,/a/d/e,/a/b.balance1,/av
// GetAccountFilesByPath(/a) => b,c,d
func GetAccountFilesByPath(prefix string) ([]File, error) {
files := make([]File, 0)
var accounts []Account
if err := conf.DB.Order(columnName("index")).Find(&accounts).Error; err != nil {
return nil, err
}
prefix = utils.ParsePath(prefix)
set := make(map[string]interface{})
for _, v := range accounts {
// 负载均衡账号
if strings.Contains(v.Name, balance) {
continue
}
full := utils.ParsePath(v.Name)
// 不是以prefix为前缀
if !strings.HasPrefix(full, prefix+"/") && prefix != "/" {
continue
}
name := strings.Split(strings.TrimPrefix(strings.TrimPrefix(full, prefix), "/"), "/")[0]
if _, ok := set[name]; ok {
continue
}
files = append(files, File{
Name: name,
Size: 0,
Driver: v.Type,
Type: conf.FOLDER,
UpdatedAt: v.UpdatedAt,
})
set[name] = nil
}
return files, nil
}

View File

@ -93,11 +93,11 @@ func LoadSettings() {
if err == nil {
conf.TextTypes = strings.Split(textTypes.Value, ",")
}
audioTypes, err := GetSettingByKey("text types")
audioTypes, err := GetSettingByKey("audio types")
if err == nil {
conf.AudioTypes = strings.Split(audioTypes.Value, ",")
}
videoTypes, err := GetSettingByKey("text types")
videoTypes, err := GetSettingByKey("video types")
if err == nil {
conf.VideoTypes = strings.Split(videoTypes.Value, ",")
}

View File

@ -1,7 +1,6 @@
package common
import (
"errors"
"fmt"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/model"
@ -25,30 +24,16 @@ type PathReq struct {
}
func ParsePath(rawPath string) (*model.Account, string, base.Driver, error) {
var path, name string
switch model.AccountsCount() {
case 0:
return nil, "", nil, fmt.Errorf("no accounts,please add one first")
case 1:
path = rawPath
break
default:
if path == "/" {
return nil, "", nil, errors.New("can't operate root of multiple accounts")
}
paths := strings.Split(rawPath, "/")
path = "/" + strings.Join(paths[2:], "/")
name = paths[1]
}
account, ok := model.GetBalancedAccount(name)
rawPath = utils.ParsePath(rawPath)
account, ok := model.GetBalancedAccount(rawPath)
if !ok {
return nil, "", nil, fmt.Errorf("no [%s] account", name)
return nil, "", nil, fmt.Errorf("path not found")
}
driver, ok := base.GetDriver(account.Type)
if !ok {
return nil, "", nil, fmt.Errorf("no [%s] driver", account.Type)
}
return &account, path, driver, nil
return &account, strings.TrimPrefix(rawPath, utils.ParsePath(account.Name)), driver, nil
}
func ErrorResp(c *gin.Context, err error, code int) {

37
server/common/files.go Normal file
View File

@ -0,0 +1,37 @@
package common
import (
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/drivers/operate"
"github.com/Xhofe/alist/model"
)
func Path(rawPath string) (*model.File, []model.File, *model.Account, base.Driver, string, error) {
account, path, driver, err := ParsePath(rawPath)
if err != nil {
if err.Error() == "path not found" {
accountFiles, err := model.GetAccountFilesByPath(rawPath)
if err != nil {
return nil, nil, nil, nil, "", err
}
if len(accountFiles) != 0 {
return nil, accountFiles, nil, nil, path, nil
}
}
return nil, nil, nil, nil, "", err
}
file, files, err := operate.Path(driver, account, path)
if err != nil {
return nil, nil, nil, nil, "", err
}
if file != nil {
return file, nil, account, driver, path, nil
} else {
accountFiles, err := model.GetAccountFilesByPath(rawPath)
if err != nil {
return nil, nil, nil, nil, "", err
}
files = append(files, accountFiles...)
return nil, files, account, driver, path, nil
}
}

View File

@ -3,6 +3,7 @@ package controllers
import (
"fmt"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/drivers/operate"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/server/common"
"github.com/gin-gonic/gin"
@ -37,7 +38,8 @@ func CreateAccount(c *gin.Context) {
common.ErrorResp(c, err, 500)
} else {
log.Debugf("new account: %+v", req)
err = driver.Save(&req, nil)
//err = driver.Save(&req, nil)
err = operate.Save(driver, &req, nil)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -71,7 +73,8 @@ func SaveAccount(c *gin.Context) {
common.ErrorResp(c, err, 500)
} else {
log.Debugf("save account: %+v", req)
err = driver.Save(&req, old)
//err = driver.Save(&req, old)
err = operate.Save(driver, &req, nil)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -93,7 +96,8 @@ func DeleteAccount(c *gin.Context) {
} else {
driver, ok := base.GetDriver(account.Type)
if ok {
_ = driver.Save(nil, account)
//_ = driver.Save(nil, account)
_ = operate.Save(driver, nil, account)
} else {
log.Errorf("no driver: %s", account.Type)
}

View File

@ -1,7 +1,6 @@
package file
import (
"github.com/Xhofe/alist/drivers/operate"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/server/common"
"github.com/gin-gonic/gin"
@ -18,31 +17,18 @@ func Folder(c *gin.Context) {
return
}
var files = make([]model.File, 0)
var err error
if model.AccountsCount() > 1 && (req.Path == "/" || req.Path == "") {
files, err = model.GetAccountFiles()
if err != nil {
common.ErrorResp(c, err, 500)
return
}
} else {
account, path, driver, err := common.ParsePath(req.Path)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
file, rawFiles, err := operate.Path(driver, account, path)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
if file != nil {
common.ErrorStrResp(c, "Not folder", 400)
}
for _, file := range rawFiles {
if file.IsDir() {
files = append(files, file)
}
_, rawFiles, _, _, _, err := common.Path(req.Path)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
if rawFiles == nil {
common.ErrorStrResp(c, "not a folder", 400)
return
}
for _, file := range rawFiles {
if file.IsDir() {
files = append(files, file)
}
}
c.JSON(200, common.Resp{

View File

@ -5,7 +5,6 @@ import (
"fmt"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/drivers/base"
"github.com/Xhofe/alist/drivers/operate"
"github.com/Xhofe/alist/model"
"github.com/Xhofe/alist/server/common"
"github.com/Xhofe/alist/utils"
@ -79,39 +78,12 @@ func Path(c *gin.Context) {
if meta != nil && meta.Upload {
upload = true
}
if model.AccountsCount() > 1 && (req.Path == "/" || req.Path == "") {
files, err := model.GetAccountFiles()
if err != nil {
common.ErrorResp(c, err, 500)
return
}
if !ok {
files = common.Hide(meta, files)
}
c.JSON(200, common.Resp{
Code: 200,
Message: "success",
Data: PathResp{
Type: "folder",
Meta: Meta{
Driver: "root",
},
Files: files,
},
})
return
}
err := CheckPagination(&req)
if err != nil {
common.ErrorResp(c, err, 400)
return
}
account, path, driver, err := common.ParsePath(req.Path)
if err != nil {
common.ErrorResp(c, err, 500)
return
}
file, files, err := operate.Path(driver, account, path)
file, files, account, driver, path, err := common.Path(req.Path)
if err != nil {
common.ErrorResp(c, err, 500)
return
@ -147,10 +119,14 @@ func Path(c *gin.Context) {
if !ok {
files = common.Hide(meta, files)
}
if driver.Config().LocalSort {
model.SortFiles(files, account)
driverName := "root"
if driver != nil {
if driver.Config().LocalSort {
model.SortFiles(files, account)
}
model.ExtractFolder(files, account)
driverName = driver.Config().Name
}
model.ExtractFolder(files, account)
total, files := Pagination(files, &req)
c.JSON(200, common.Resp{
Code: 200,
@ -158,7 +134,7 @@ func Path(c *gin.Context) {
Data: PathResp{
Type: "folder",
Meta: Meta{
Driver: driver.Config().Name,
Driver: driverName,
Upload: upload,
Total: total,
},

View File

@ -50,17 +50,18 @@ func (fs *FileSystem) File(rawPath string) (*model.File, error) {
func (fs *FileSystem) Files(ctx context.Context, rawPath string) ([]model.File, error) {
rawPath = utils.ParsePath(rawPath)
var files []model.File
var err error
if model.AccountsCount() > 1 && rawPath == "/" {
files, err = model.GetAccountFiles()
} else {
account, path_, driver, err := common.ParsePath(rawPath)
if err != nil {
return nil, err
}
files, err = operate.Files(driver, account, path_)
}
//var files []model.File
//var err error
//if model.AccountsCount() > 1 && rawPath == "/" {
// files, err = model.GetAccountFilesByPath("/")
//} else {
// account, path_, driver, err := common.ParsePath(rawPath)
// if err != nil {
// return nil, err
// }
// files, err = operate.Files(driver, account, path_)
//}
_, files, _, _, _, err := common.Path(rawPath)
if err != nil {
return nil, err
}
@ -125,10 +126,10 @@ func (fs *FileSystem) Link(w http.ResponseWriter, r *http.Request, rawPath strin
}
if driver.Config().OnlyProxy || account.WebdavProxy {
link = fmt.Sprintf("%s://%s/p%s", protocol, r.Host, rawPath)
if conf.GetBool("check down link") {
sign := utils.SignWithToken(utils.Base(rawPath), conf.Token)
link += "?sign=" + sign
}
//if conf.GetBool("check down link") {
sign := utils.SignWithToken(utils.Base(rawPath), conf.Token)
link += "?sign=" + sign
//}
} else {
link_, err := driver.Link(base.Args{Path: path_, IP: ClientIP(r)}, account)
if err != nil {

59
utils/cookie/cookie.go Normal file
View File

@ -0,0 +1,59 @@
package cookie
import (
"net/http"
"strings"
)
func Parse(str string) []*http.Cookie {
header := http.Header{}
header.Add("Cookie", str)
request := http.Request{Header: header}
return request.Cookies()
}
func ToString(cookies []*http.Cookie) string {
if cookies == nil {
return ""
}
cookieStrings := make([]string, len(cookies))
for i, cookie := range cookies {
cookieStrings[i] = cookie.String()
}
return strings.Join(cookieStrings, ";")
}
func SetCookie(cookies []*http.Cookie, name, value string) []*http.Cookie {
for i, cookie := range cookies {
if cookie.Name == name {
cookies[i].Value = value
return cookies
}
}
cookies = append(cookies, &http.Cookie{Name: name, Value: value})
return cookies
}
func GetCookie(cookies []*http.Cookie, name string) *http.Cookie {
for _, cookie := range cookies {
if cookie.Name == name {
return cookie
}
}
return nil
}
func SetStr(cookiesStr, name, value string) string {
cookies := Parse(cookiesStr)
cookies = SetCookie(cookies, name, value)
return ToString(cookies)
}
func GetStr(cookiesStr, name string) string {
cookies := Parse(cookiesStr)
cookie := GetCookie(cookies, name)
if cookie == nil {
return ""
}
return cookie.Value
}