Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
21ca2f11b7 | |||
ccaa28a323 | |||
fea8b376f8 | |||
55d244b726 | |||
1640a52789 | |||
424ec10692 | |||
b472c2ee18 | |||
65a01251e9 | |||
96be6bbbd1 | |||
6f7465aab7 | |||
c9bc8227bb |
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -33,8 +33,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up xgo
|
- name: Set up xgo
|
||||||
run: |
|
run: |
|
||||||
docker pull crazymax/xgo:latest
|
docker pull techknowlogick/xgo:latest
|
||||||
go install github.com/crazy-max/xgo@latest
|
go install src.techknowlogick.com/xgo@latest
|
||||||
sudo apt install upx
|
sudo apt install upx
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -29,8 +29,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up xgo
|
- name: Set up xgo
|
||||||
run: |
|
run: |
|
||||||
docker pull crazymax/xgo:latest
|
docker pull techknowlogick/xgo:latest
|
||||||
go install github.com/crazy-max/xgo@latest
|
go install src.techknowlogick.com/xgo@latest
|
||||||
sudo apt install upx
|
sudo apt install upx
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,7 +23,7 @@ dist/
|
|||||||
bin/*
|
bin/*
|
||||||
/alist
|
/alist
|
||||||
*.json
|
*.json
|
||||||
public/index.html
|
public/*.html
|
||||||
public/assets/
|
public/assets/
|
||||||
public/public/
|
public/public/
|
||||||
data/
|
data/
|
@ -33,7 +33,7 @@ func InitConf() {
|
|||||||
}
|
}
|
||||||
log.Debugf("config:%+v", conf.Conf)
|
log.Debugf("config:%+v", conf.Conf)
|
||||||
// update config.json struct
|
// update config.json struct
|
||||||
confBody, err := utils.Json.Marshal(conf.Conf)
|
confBody, err := utils.Json.MarshalIndent(conf.Conf, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("marshal config error:%s", err.Error())
|
log.Fatalf("marshal config error:%s", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ type CacheConfig struct {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
Local bool `json:"local"`
|
Assets string `json:"assets"`
|
||||||
Database Database `json:"database"`
|
Database Database `json:"database"`
|
||||||
Scheme Scheme `json:"scheme"`
|
Scheme Scheme `json:"scheme"`
|
||||||
Cache CacheConfig `json:"cache"`
|
Cache CacheConfig `json:"cache"`
|
||||||
@ -35,6 +35,7 @@ func DefaultConfig() *Config {
|
|||||||
return &Config{
|
return &Config{
|
||||||
Address: "0.0.0.0",
|
Address: "0.0.0.0",
|
||||||
Port: 5244,
|
Port: 5244,
|
||||||
|
Assets: "zhimg",
|
||||||
Database: Database{
|
Database: Database{
|
||||||
Type: "sqlite3",
|
Type: "sqlite3",
|
||||||
Port: 0,
|
Port: 0,
|
||||||
|
@ -158,7 +158,7 @@ func (driver Cloud139) GetLink(contentId string, account *model.Account) (string
|
|||||||
"appName": "",
|
"appName": "",
|
||||||
"contentID": contentId,
|
"contentID": contentId,
|
||||||
"commonAccountInfo": base.Json{
|
"commonAccountInfo": base.Json{
|
||||||
"account": "18627147660",
|
"account": account.Username,
|
||||||
"accountType": 1,
|
"accountType": 1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,12 @@ func (driver Cloud139) Link(args base.Args, account *model.Account) (*base.Link,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
u, err := driver.GetLink(file.Id, account)
|
var u string
|
||||||
|
//if isFamily(account) {
|
||||||
|
// u, err = driver.familyLink(file.Id, account)
|
||||||
|
//} else {
|
||||||
|
u, err = driver.GetLink(file.Id, account)
|
||||||
|
//}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -53,15 +53,22 @@ func (driver FTP) Items() []base.Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (driver FTP) Save(account *model.Account, old *model.Account) error {
|
func (driver FTP) Save(account *model.Account, old *model.Account) error {
|
||||||
|
if old != nil {
|
||||||
|
conn, ok := connMap[old.Name]
|
||||||
|
if ok {
|
||||||
|
err := conn.Quit()
|
||||||
|
log.Error("ftp:", err)
|
||||||
|
delete(connMap, old.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
if account.RootFolder == "" {
|
if account.RootFolder == "" {
|
||||||
account.RootFolder = "/"
|
account.RootFolder = "/"
|
||||||
}
|
}
|
||||||
conn, err := driver.Login(account)
|
_, err := driver.Login(account)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
account.Status = err.Error()
|
account.Status = err.Error()
|
||||||
} else {
|
} else {
|
||||||
account.Status = "work"
|
account.Status = "work"
|
||||||
_ = conn.Quit()
|
|
||||||
}
|
}
|
||||||
_ = model.SaveAccount(account)
|
_ = model.SaveAccount(account)
|
||||||
return err
|
return err
|
||||||
@ -106,7 +113,7 @@ func (driver FTP) Files(path string, account *model.Account) ([]model.File, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
entries, err := conn.List(realPath)
|
entries, err := conn.List(realPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -144,7 +151,7 @@ func (driver FTP) Link(args base.Args, account *model.Account) (*base.Link, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
resp, err := conn.Retr(realPath)
|
resp, err := conn.Retr(realPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -191,7 +198,7 @@ func (driver FTP) MakeDir(path string, account *model.Account) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
err = conn.MakeDir(realPath)
|
err = conn.MakeDir(realPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -203,7 +210,7 @@ func (driver FTP) Move(src string, dst string, account *model.Account) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
err = conn.Rename(realSrc, realDst)
|
err = conn.Rename(realSrc, realDst)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -223,7 +230,7 @@ func (driver FTP) Delete(path string, account *model.Account) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
err = conn.Delete(realPath)
|
err = conn.Delete(realPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -237,7 +244,7 @@ func (driver FTP) Upload(file *model.FileStream, account *model.Account) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer func() { _ = conn.Quit() }()
|
//defer func() { _ = conn.Quit() }()
|
||||||
err = conn.Stor(realPath, file)
|
err = conn.Stor(realPath, file)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,13 @@ import (
|
|||||||
"github.com/jlaffaye/ftp"
|
"github.com/jlaffaye/ftp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var connMap map[string]*ftp.ServerConn
|
||||||
|
|
||||||
func (driver FTP) Login(account *model.Account) (*ftp.ServerConn, error) {
|
func (driver FTP) Login(account *model.Account) (*ftp.ServerConn, error) {
|
||||||
|
conn, ok := connMap[account.Name]
|
||||||
|
if ok {
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
conn, err := ftp.Connect(account.SiteUrl)
|
conn, err := ftp.Connect(account.SiteUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -20,4 +26,4 @@ func (driver FTP) Login(account *model.Account) (*ftp.ServerConn, error) {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
base.RegisterDriver(&FTP{})
|
base.RegisterDriver(&FTP{})
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,13 @@ func (driver MediaTrack) Items() []base.Item {
|
|||||||
Label: "Token",
|
Label: "Token",
|
||||||
Type: base.TypeString,
|
Type: base.TypeString,
|
||||||
Description: "Unknown expiration time",
|
Description: "Unknown expiration time",
|
||||||
|
Required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "root_folder",
|
Name: "root_folder",
|
||||||
Label: "root folder file_id",
|
Label: "root folder file_id",
|
||||||
Type: base.TypeString,
|
Type: base.TypeString,
|
||||||
|
Required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "order_by",
|
Name: "order_by",
|
||||||
@ -155,7 +157,7 @@ func (driver MediaTrack) MakeDir(path string, account *model.Account) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v4/assets/%s/children", parentFile.Id)
|
url := fmt.Sprintf("https://jayce.api.mediatrack.cn/v3/assets/%s/children", parentFile.Id)
|
||||||
_, err = driver.Request(url, base.Post, nil, nil, nil, base.Json{
|
_, err = driver.Request(url, base.Post, nil, nil, nil, base.Json{
|
||||||
"type": 1,
|
"type": 1,
|
||||||
"title": utils.Base(path),
|
"title": utils.Base(path),
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/Xhofe/alist/model"
|
"github.com/Xhofe/alist/model"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
@ -58,6 +59,7 @@ func (driver MediaTrack) Request(url string, method int, headers, query, form ma
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
log.Debugln(res.String())
|
||||||
if e.Status != "SUCCESS" {
|
if e.Status != "SUCCESS" {
|
||||||
return nil, errors.New(e.Message)
|
return nil, errors.New(e.Message)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/Xhofe/alist/drivers/base"
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
"github.com/Xhofe/alist/model"
|
"github.com/Xhofe/alist/model"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeDir(driver base.Driver, account *model.Account, path string, clearCache bool) error {
|
func MakeDir(driver base.Driver, account *model.Account, path string, clearCache bool) error {
|
||||||
@ -11,6 +12,9 @@ func MakeDir(driver base.Driver, account *model.Account, path string, clearCache
|
|||||||
if err == nil && clearCache {
|
if err == nil && clearCache {
|
||||||
_ = base.DeleteCache(utils.Dir(path), account)
|
_ = base.DeleteCache(utils.Dir(path), account)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("mkdir error: %s", err.Error())
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +35,9 @@ func Move(driver base.Driver, account *model.Account, src, dst string, clearCach
|
|||||||
_ = base.DeleteCache(utils.Dir(dst), account)
|
_ = base.DeleteCache(utils.Dir(dst), account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("move error: %s", err.Error())
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,6 +46,9 @@ func Copy(driver base.Driver, account *model.Account, src, dst string, clearCach
|
|||||||
if err == nil && clearCache {
|
if err == nil && clearCache {
|
||||||
_ = base.DeleteCache(utils.Dir(dst), account)
|
_ = base.DeleteCache(utils.Dir(dst), account)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("copy error: %s", err.Error())
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +57,9 @@ func Delete(driver base.Driver, account *model.Account, path string, clearCache
|
|||||||
if err == nil && clearCache {
|
if err == nil && clearCache {
|
||||||
_ = base.DeleteCache(utils.Dir(path), account)
|
_ = base.DeleteCache(utils.Dir(path), account)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("delete error: %s", err.Error())
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,5 +71,8 @@ func Upload(driver base.Driver, account *model.Account, file *model.FileStream,
|
|||||||
if err == nil && clearCache {
|
if err == nil && clearCache {
|
||||||
_ = base.DeleteCache(file.ParentPath, account)
|
_ = base.DeleteCache(file.ParentPath, account)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("upload error: %s", err.Error())
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,16 @@ func ErrorResp(c *gin.Context, err error, code int) {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ErrorStrResp(c *gin.Context, str string, code int) {
|
||||||
|
log.Error(str)
|
||||||
|
c.JSON(200, Resp{
|
||||||
|
Code: code,
|
||||||
|
Message: str,
|
||||||
|
Data: nil,
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
|
||||||
func SuccessResp(c *gin.Context, data ...interface{}) {
|
func SuccessResp(c *gin.Context, data ...interface{}) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
c.JSON(200, Resp{
|
c.JSON(200, Resp{
|
||||||
|
@ -28,7 +28,7 @@ func CreateAccount(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
driver, ok := base.GetDriver(req.Type)
|
driver, ok := base.GetDriver(req.Type)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.ErrorResp(c, fmt.Errorf("no [%s] driver", req.Type), 400)
|
common.ErrorStrResp(c, fmt.Sprintf("No [%s] driver", req.Type), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@ -54,7 +54,7 @@ func SaveAccount(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
driver, ok := base.GetDriver(req.Type)
|
driver, ok := base.GetDriver(req.Type)
|
||||||
if !ok {
|
if !ok {
|
||||||
common.ErrorResp(c, fmt.Errorf("no [%s] driver", req.Type), 400)
|
common.ErrorStrResp(c, fmt.Sprintf("No [%s] driver", req.Type), 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
old, err := model.GetAccountById(req.ID)
|
old, err := model.GetAccountById(req.ID)
|
||||||
|
@ -1,21 +1,11 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
|
||||||
"github.com/Xhofe/alist/drivers/base"
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-resty/resty/v2"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Down(c *gin.Context) {
|
func Down(c *gin.Context) {
|
||||||
@ -39,129 +29,3 @@ func Down(c *gin.Context) {
|
|||||||
c.Redirect(302, link.Url)
|
c.Redirect(302, link.Url)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func Proxy(c *gin.Context) {
|
|
||||||
rawPath := c.Param("path")
|
|
||||||
rawPath = utils.ParsePath(rawPath)
|
|
||||||
log.Debugf("proxy: %s", rawPath)
|
|
||||||
account, path, driver, err := common.ParsePath(rawPath)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 只有以下几种情况允许中转:
|
|
||||||
// 1. 账号开启中转
|
|
||||||
// 2. driver只能中转
|
|
||||||
// 3. 是文本类型文件
|
|
||||||
// 4. 开启webdav中转(需要验证sign)
|
|
||||||
if !account.Proxy && !driver.Config().OnlyProxy && utils.GetFileType(filepath.Ext(rawPath)) != conf.TEXT {
|
|
||||||
// 只开启了webdav中转,验证sign
|
|
||||||
ok := false
|
|
||||||
if account.WebdavProxy {
|
|
||||||
_, ok = c.Get("sign")
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
common.ErrorResp(c, fmt.Errorf("[%s] not allowed proxy", account.Name), 403)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 中转时有中转机器使用中转机器,若携带标志位则表明不能再走中转机器了
|
|
||||||
if account.DownProxyUrl != "" && c.Query("d") != "1" {
|
|
||||||
name := utils.Base(rawPath)
|
|
||||||
link := fmt.Sprintf("%s%s?sign=%s", account.DownProxyUrl, rawPath, utils.SignWithToken(name, conf.Token))
|
|
||||||
c.Redirect(302, link)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 对于中转,不需要重设IP
|
|
||||||
link, err := driver.Link(base.Args{Path: path}, account)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 本机读取数据
|
|
||||||
if link.Data != nil {
|
|
||||||
//c.Data(http.StatusOK, "application/octet-stream", link.Data)
|
|
||||||
defer func() {
|
|
||||||
_ = link.Data.Close()
|
|
||||||
}()
|
|
||||||
c.Status(http.StatusOK)
|
|
||||||
c.Header("content", "application/octet-stream")
|
|
||||||
_, err = io.Copy(c.Writer, link.Data)
|
|
||||||
if err != nil {
|
|
||||||
_, _ = c.Writer.WriteString(err.Error())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 本机文件直接返回文件
|
|
||||||
if account.Type == "Native" {
|
|
||||||
// 对于名称为index.html的文件需要特殊处理
|
|
||||||
if utils.Base(rawPath) == "index.html" {
|
|
||||||
file, err := os.Open(link.Url)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
_ = file.Close()
|
|
||||||
}()
|
|
||||||
fileStat, err := os.Stat(link.Url)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.ServeContent(c.Writer, c.Request, utils.Base(rawPath), fileStat.ModTime(), file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.File(link.Url)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
if utils.GetFileType(filepath.Ext(rawPath)) == conf.TEXT {
|
|
||||||
Text(c, link)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
driver.Proxy(c, account)
|
|
||||||
r := c.Request
|
|
||||||
w := c.Writer
|
|
||||||
target, err := url.Parse(link.Url)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
protocol := "http://"
|
|
||||||
if strings.HasPrefix(link.Url, "https://") {
|
|
||||||
protocol = "https://"
|
|
||||||
}
|
|
||||||
targetHost, err := url.Parse(fmt.Sprintf("%s%s", protocol, target.Host))
|
|
||||||
proxy := httputil.NewSingleHostReverseProxy(targetHost)
|
|
||||||
r.URL = target
|
|
||||||
r.Host = target.Host
|
|
||||||
proxy.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var client *resty.Client
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
client = resty.New()
|
|
||||||
client.SetRetryCount(3)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Text(c *gin.Context, link *base.Link) {
|
|
||||||
res, err := client.R().Get(link.Url)
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
text := res.String()
|
|
||||||
t := utils.GetStrCoding(res.Body())
|
|
||||||
log.Debugf("text type: %s", t)
|
|
||||||
if t != utils.UTF8 {
|
|
||||||
body, err := utils.GbkToUtf8(res.Body())
|
|
||||||
if err != nil {
|
|
||||||
common.ErrorResp(c, err, 500)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
text = string(body)
|
|
||||||
}
|
|
||||||
c.String(200, text)
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/Xhofe/alist/drivers/base"
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
"github.com/Xhofe/alist/drivers/operate"
|
"github.com/Xhofe/alist/drivers/operate"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
@ -21,7 +20,7 @@ func DeleteFiles(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(req.Names) == 0 {
|
if len(req.Names) == 0 {
|
||||||
common.ErrorResp(c, errors.New("empty file names"), 400)
|
common.ErrorStrResp(c, "Empty file names", 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for i, name := range req.Names {
|
for i, name := range req.Names {
|
||||||
@ -30,6 +29,10 @@ func DeleteFiles(c *gin.Context) {
|
|||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if path_ == "/" {
|
||||||
|
common.ErrorStrResp(c, "Delete root folder is not allowed", 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
clearCache := false
|
clearCache := false
|
||||||
if i == len(req.Names)-1 {
|
if i == len(req.Names)-1 {
|
||||||
clearCache = true
|
clearCache = true
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package file
|
package file
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/drivers/base"
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
"github.com/Xhofe/alist/drivers/operate"
|
"github.com/Xhofe/alist/drivers/operate"
|
||||||
@ -19,11 +18,11 @@ func UploadFiles(c *gin.Context) {
|
|||||||
password := c.PostForm("password")
|
password := c.PostForm("password")
|
||||||
meta, _ := model.GetMetaByPath(path)
|
meta, _ := model.GetMetaByPath(path)
|
||||||
if meta == nil || !meta.Upload {
|
if meta == nil || !meta.Upload {
|
||||||
common.ErrorResp(c, errors.New("not allow upload"), 403)
|
common.ErrorStrResp(c, "Not allow upload", 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if meta.Password != "" && meta.Password != password {
|
if meta.Password != "" && meta.Password != password {
|
||||||
common.ErrorResp(c, errors.New("wrong password"), 403)
|
common.ErrorStrResp(c, "Wrong password", 403)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,7 @@ type PathResp struct {
|
|||||||
func Path(c *gin.Context) {
|
func Path(c *gin.Context) {
|
||||||
reqV, _ := c.Get("req")
|
reqV, _ := c.Get("req")
|
||||||
req := reqV.(common.PathReq)
|
req := reqV.(common.PathReq)
|
||||||
|
_, ok := c.Get("admin")
|
||||||
meta, _ := model.GetMetaByPath(req.Path)
|
meta, _ := model.GetMetaByPath(req.Path)
|
||||||
upload := false
|
upload := false
|
||||||
if meta != nil && meta.Upload {
|
if meta != nil && meta.Upload {
|
||||||
@ -98,7 +99,9 @@ func Path(c *gin.Context) {
|
|||||||
common.ErrorResp(c, err, 500)
|
common.ErrorResp(c, err, 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
files = Hide(meta, files)
|
if !ok {
|
||||||
|
files = Hide(meta, files)
|
||||||
|
}
|
||||||
c.JSON(200, common.Resp{
|
c.JSON(200, common.Resp{
|
||||||
Code: 200,
|
Code: 200,
|
||||||
Message: "success",
|
Message: "success",
|
||||||
@ -155,7 +158,9 @@ func Path(c *gin.Context) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
files = Hide(meta, files)
|
if !ok {
|
||||||
|
files = Hide(meta, files)
|
||||||
|
}
|
||||||
if driver.Config().LocalSort {
|
if driver.Config().LocalSort {
|
||||||
model.SortFiles(files, account)
|
model.SortFiles(files, account)
|
||||||
}
|
}
|
||||||
|
166
server/controllers/proxy.go
Normal file
166
server/controllers/proxy.go
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/Xhofe/alist/conf"
|
||||||
|
"github.com/Xhofe/alist/drivers/base"
|
||||||
|
"github.com/Xhofe/alist/server/common"
|
||||||
|
"github.com/Xhofe/alist/utils"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Proxy(c *gin.Context) {
|
||||||
|
rawPath := c.Param("path")
|
||||||
|
rawPath = utils.ParsePath(rawPath)
|
||||||
|
log.Debugf("proxy: %s", rawPath)
|
||||||
|
account, path, driver, err := common.ParsePath(rawPath)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 只有以下几种情况允许中转:
|
||||||
|
// 1. 账号开启中转
|
||||||
|
// 2. driver只能中转
|
||||||
|
// 3. 是文本类型文件
|
||||||
|
// 4. 开启webdav中转(需要验证sign)
|
||||||
|
if !account.Proxy && !driver.Config().OnlyProxy && utils.GetFileType(filepath.Ext(rawPath)) != conf.TEXT {
|
||||||
|
// 只开启了webdav中转,验证sign
|
||||||
|
ok := false
|
||||||
|
if account.WebdavProxy {
|
||||||
|
_, ok = c.Get("sign")
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
common.ErrorStrResp(c, fmt.Sprintf("[%s] not allowed proxy", account.Name), 403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 中转时有中转机器使用中转机器,若携带标志位则表明不能再走中转机器了
|
||||||
|
if account.DownProxyUrl != "" && c.Query("d") != "1" {
|
||||||
|
name := utils.Base(rawPath)
|
||||||
|
link := fmt.Sprintf("%s%s?sign=%s", account.DownProxyUrl, rawPath, utils.SignWithToken(name, conf.Token))
|
||||||
|
c.Redirect(302, link)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 检查文件
|
||||||
|
file, err := driver.File(path, account)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 对于中转,不需要重设IP
|
||||||
|
link, err := driver.Link(base.Args{Path: path}, account)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 本机读取数据
|
||||||
|
if link.Data != nil {
|
||||||
|
//c.Data(http.StatusOK, "application/octet-stream", link.Data)
|
||||||
|
defer func() {
|
||||||
|
_ = link.Data.Close()
|
||||||
|
}()
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
c.Header("Content-Type", "application/octet-stream")
|
||||||
|
c.Header("Content-Disposition", fmt.Sprintf(`attachment; filename=%s`, url.QueryEscape(file.Name)))
|
||||||
|
c.Header("Content-Length", strconv.FormatInt(file.Size, 10))
|
||||||
|
_, err = io.Copy(c.Writer, link.Data)
|
||||||
|
if err != nil {
|
||||||
|
_, _ = c.Writer.WriteString(err.Error())
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 本机文件直接返回文件
|
||||||
|
if account.Type == "Native" {
|
||||||
|
// 对于名称为index.html的文件需要特殊处理
|
||||||
|
if utils.Base(rawPath) == "index.html" {
|
||||||
|
file, err := os.Open(link.Url)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = file.Close()
|
||||||
|
}()
|
||||||
|
fileStat, err := os.Stat(link.Url)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http.ServeContent(c.Writer, c.Request, utils.Base(rawPath), fileStat.ModTime(), file)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.File(link.Url)
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if utils.GetFileType(filepath.Ext(rawPath)) == conf.TEXT {
|
||||||
|
Text(c, link)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
driver.Proxy(c, account)
|
||||||
|
r := c.Request
|
||||||
|
w := c.Writer
|
||||||
|
//target, err := url.Parse(link.Url)
|
||||||
|
//if err != nil {
|
||||||
|
// common.ErrorResp(c, err, 500)
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
req, err := http.NewRequest("GET", link.Url, nil)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for h, val := range r.Header {
|
||||||
|
req.Header[h] = val
|
||||||
|
}
|
||||||
|
res, err := HttpClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(res.StatusCode)
|
||||||
|
for h, v := range res.Header {
|
||||||
|
w.Header()[h] = v
|
||||||
|
}
|
||||||
|
_, err = io.Copy(w, res.Body)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var client *resty.Client
|
||||||
|
var HttpClient = &http.Client{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
client = resty.New()
|
||||||
|
client.SetRetryCount(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Text(c *gin.Context, link *base.Link) {
|
||||||
|
res, err := client.R().Get(link.Url)
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
text := res.String()
|
||||||
|
t := utils.GetStrCoding(res.Body())
|
||||||
|
log.Debugf("text type: %s", t)
|
||||||
|
if t != utils.UTF8 {
|
||||||
|
body, err := utils.GbkToUtf8(res.Body())
|
||||||
|
if err != nil {
|
||||||
|
common.ErrorResp(c, err, 500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
text = string(body)
|
||||||
|
}
|
||||||
|
c.String(200, text)
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/model"
|
"github.com/Xhofe/alist/model"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -9,8 +8,8 @@ import (
|
|||||||
|
|
||||||
func CheckAccount(c *gin.Context) {
|
func CheckAccount(c *gin.Context) {
|
||||||
if model.AccountsCount() == 0 {
|
if model.AccountsCount() == 0 {
|
||||||
common.ErrorResp(c, fmt.Errorf("no accounts,please add one first"), 1001)
|
common.ErrorStrResp(c, "No accounts,please add one first", 1001)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -20,8 +19,8 @@ func Auth(c *gin.Context) {
|
|||||||
//}
|
//}
|
||||||
//if token != utils.GetMD5Encode(password.Value) {
|
//if token != utils.GetMD5Encode(password.Value) {
|
||||||
if token != conf.Token {
|
if token != conf.Token {
|
||||||
common.ErrorResp(c, fmt.Errorf("wrong password"), 401)
|
common.ErrorStrResp(c, "Wrong password", 401)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
"github.com/Xhofe/alist/utils"
|
"github.com/Xhofe/alist/utils"
|
||||||
@ -20,7 +19,7 @@ func DownCheck(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
pw := c.Query("pw")
|
pw := c.Query("pw")
|
||||||
if !common.CheckDownLink(utils.Dir(rawPath), pw, utils.Base(rawPath)) {
|
if !common.CheckDownLink(utils.Dir(rawPath), pw, utils.Base(rawPath)) {
|
||||||
common.ErrorResp(c, fmt.Errorf("wrong password"), 401)
|
common.ErrorStrResp(c, "Wrong password", 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package middlewares
|
package middlewares
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/model"
|
"github.com/Xhofe/alist/model"
|
||||||
"github.com/Xhofe/alist/server/common"
|
"github.com/Xhofe/alist/server/common"
|
||||||
@ -19,19 +18,20 @@ func PathCheck(c *gin.Context) {
|
|||||||
c.Set("req", req)
|
c.Set("req", req)
|
||||||
token := c.GetHeader("Authorization")
|
token := c.GetHeader("Authorization")
|
||||||
if token == conf.Token {
|
if token == conf.Token {
|
||||||
|
c.Set("admin", true)
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
meta, err := model.GetMetaByPath(req.Path)
|
meta, err := model.GetMetaByPath(req.Path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if meta.Password != "" && meta.Password != req.Password {
|
if meta.Password != "" && meta.Password != req.Password {
|
||||||
common.ErrorResp(c, fmt.Errorf("wrong password"), 401)
|
common.ErrorStrResp(c, "Wrong password", 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else if conf.GetBool("check parent folder") {
|
} else if conf.GetBool("check parent folder") {
|
||||||
if !common.CheckParent(utils.Dir(req.Path), req.Password) {
|
if !common.CheckParent(utils.Dir(req.Path), req.Password) {
|
||||||
common.ErrorResp(c, fmt.Errorf("wrong password"), 401)
|
common.ErrorStrResp(c, "Wrong password", 401)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/Xhofe/alist/conf"
|
"github.com/Xhofe/alist/conf"
|
||||||
"github.com/Xhofe/alist/public"
|
"github.com/Xhofe/alist/public"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@ -14,13 +15,17 @@ import (
|
|||||||
func InitIndex() {
|
func InitIndex() {
|
||||||
var index fs.File
|
var index fs.File
|
||||||
var err error
|
var err error
|
||||||
if conf.Conf.Local {
|
//if conf.Conf.Local {
|
||||||
index, err = public.Public.Open("local.html")
|
// index, err = public.Public.Open("local.html")
|
||||||
} else {
|
//} else {
|
||||||
index, err = public.Public.Open("index.html")
|
// index, err = public.Public.Open("index.html")
|
||||||
|
//}
|
||||||
|
if conf.Conf.Assets == "" {
|
||||||
|
conf.Conf.Assets = conf.DefaultConfig().Assets
|
||||||
}
|
}
|
||||||
|
index, err = public.Public.Open(fmt.Sprintf("%s.html", conf.Conf.Assets))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//log.Fatalf(err.Error())
|
log.Fatalf(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, _ := ioutil.ReadAll(index)
|
data, _ := ioutil.ReadAll(index)
|
||||||
|
Reference in New Issue
Block a user