* refactor: FilterReadMeScripts * .
This commit is contained in:
parent
3499c4db87
commit
b4e6ab12d9
@ -316,7 +316,7 @@ func (d *Quqi) Put(ctx context.Context, dstDir model.Obj, stream model.FileStrea
|
|||||||
// if the file already exists in Quqi server, there is no need to actually upload it
|
// if the file already exists in Quqi server, there is no need to actually upload it
|
||||||
if uploadInitResp.Data.Exist {
|
if uploadInitResp.Data.Exist {
|
||||||
// the file name returned by Quqi does not include the extension name
|
// the file name returned by Quqi does not include the extension name
|
||||||
nodeName, nodeExt := uploadInitResp.Data.NodeName, rawExt(stream.GetName())
|
nodeName, nodeExt := uploadInitResp.Data.NodeName, utils.Ext(stream.GetName())
|
||||||
if nodeExt != "" {
|
if nodeExt != "" {
|
||||||
nodeName = nodeName + "." + nodeExt
|
nodeName = nodeName + "." + nodeExt
|
||||||
}
|
}
|
||||||
@ -432,7 +432,7 @@ func (d *Quqi) Put(ctx context.Context, dstDir model.Obj, stream model.FileStrea
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// the file name returned by Quqi does not include the extension name
|
// the file name returned by Quqi does not include the extension name
|
||||||
nodeName, nodeExt := uploadFinishResp.Data.NodeName, rawExt(stream.GetName())
|
nodeName, nodeExt := uploadFinishResp.Data.NodeName, utils.Ext(stream.GetName())
|
||||||
if nodeExt != "" {
|
if nodeExt != "" {
|
||||||
nodeName = nodeName + "." + nodeExt
|
nodeName = nodeName + "." + nodeExt
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
stdpath "path"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -115,16 +114,6 @@ func (d *Quqi) checkLogin() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawExt 保留扩展名大小写
|
|
||||||
func rawExt(name string) string {
|
|
||||||
ext := stdpath.Ext(name)
|
|
||||||
if strings.HasPrefix(ext, ".") {
|
|
||||||
ext = ext[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ext
|
|
||||||
}
|
|
||||||
|
|
||||||
// decryptKey 获取密码
|
// decryptKey 获取密码
|
||||||
func decryptKey(encodeKey string) []byte {
|
func decryptKey(encodeKey string) []byte {
|
||||||
// 移除非法字符
|
// 移除非法字符
|
||||||
|
@ -8,9 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
@ -151,7 +149,7 @@ func (d *Vtencent) ApplyUploadUGC(signature string, stream model.FileStreamer) (
|
|||||||
form := base.Json{
|
form := base.Json{
|
||||||
"signature": signature,
|
"signature": signature,
|
||||||
"videoName": stream.GetName(),
|
"videoName": stream.GetName(),
|
||||||
"videoType": strings.ReplaceAll(path.Ext(stream.GetName()), ".", ""),
|
"videoType": utils.Ext(stream.GetName()),
|
||||||
"videoSize": stream.GetSize(),
|
"videoSize": stream.GetSize(),
|
||||||
}
|
}
|
||||||
var resps RspApplyUploadUGC
|
var resps RspApplyUploadUGC
|
||||||
|
@ -619,10 +619,9 @@ type Buf struct {
|
|||||||
// NewBuf is a buffer that can have 1 read & 1 write at the same time.
|
// NewBuf is a buffer that can have 1 read & 1 write at the same time.
|
||||||
// when read is faster write, immediately feed data to read after written
|
// when read is faster write, immediately feed data to read after written
|
||||||
func NewBuf(ctx context.Context, maxSize int) *Buf {
|
func NewBuf(ctx context.Context, maxSize int) *Buf {
|
||||||
d := make([]byte, 0, maxSize)
|
|
||||||
return &Buf{
|
return &Buf{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
buffer: bytes.NewBuffer(d),
|
buffer: bytes.NewBuffer(make([]byte, 0, maxSize)),
|
||||||
size: maxSize,
|
size: maxSize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -677,5 +676,5 @@ func (br *Buf) Write(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (br *Buf) Close() {
|
func (br *Buf) Close() {
|
||||||
br.buffer.Reset()
|
br.buffer = nil
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func IsSubPath(path string, subPath string) bool {
|
|||||||
|
|
||||||
func Ext(path string) string {
|
func Ext(path string) string {
|
||||||
ext := stdpath.Ext(path)
|
ext := stdpath.Ext(path)
|
||||||
if strings.HasPrefix(ext, ".") {
|
if len(ext) > 0 && ext[0] == '.' {
|
||||||
ext = ext[1:]
|
ext = ext[1:]
|
||||||
}
|
}
|
||||||
return strings.ToLower(ext)
|
return strings.ToLower(ext)
|
||||||
|
@ -1,97 +1,25 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"maps"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/net"
|
"github.com/alist-org/alist/v3/internal/net"
|
||||||
"github.com/alist-org/alist/v3/internal/setting"
|
|
||||||
"github.com/alist-org/alist/v3/internal/stream"
|
"github.com/alist-org/alist/v3/internal/stream"
|
||||||
"github.com/alist-org/alist/v3/pkg/http_range"
|
"github.com/alist-org/alist/v3/pkg/http_range"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/microcosm-cc/bluemonday"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/yuin/goldmark"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func processMarkdown(content []byte) ([]byte, error) {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := goldmark.New().Convert(content, &buf); err != nil {
|
|
||||||
return nil, fmt.Errorf("markdown conversion failed: %w", err)
|
|
||||||
}
|
|
||||||
return bluemonday.UGCPolicy().SanitizeBytes(buf.Bytes()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.Obj) error {
|
func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.Obj) error {
|
||||||
|
|
||||||
//优先处理md文件
|
|
||||||
if utils.Ext(file.GetName()) == "md" && setting.GetBool(conf.FilterReadMeScripts) {
|
|
||||||
var markdownContent []byte
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if link.MFile != nil {
|
|
||||||
defer link.MFile.Close()
|
|
||||||
attachHeader(w, file)
|
|
||||||
markdownContent, err = io.ReadAll(link.MFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read markdown content: %w", err)
|
|
||||||
}
|
|
||||||
} else if link.RangeReadCloser != nil {
|
|
||||||
attachHeader(w, file)
|
|
||||||
rrc, err := link.RangeReadCloser.RangeRead(r.Context(), http_range.Range{Start: 0, Length: -1})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer rrc.Close()
|
|
||||||
markdownContent, err = io.ReadAll(rrc)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read markdown content: %w", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
header := net.ProcessHeader(r.Header, link.Header)
|
|
||||||
res, err := net.RequestHttp(r.Context(), r.Method, header, link.URL)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
for h, v := range res.Header {
|
|
||||||
w.Header()[h] = v
|
|
||||||
}
|
|
||||||
w.WriteHeader(res.StatusCode)
|
|
||||||
if r.Method == http.MethodHead {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
markdownContent, err = io.ReadAll(res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read markdown content: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
safeHTML, err := processMarkdown(markdownContent)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
safeHTMLReader := bytes.NewReader(safeHTML)
|
|
||||||
w.Header().Set("Content-Length", strconv.FormatInt(int64(len(safeHTML)), 10))
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
_, err = utils.CopyWithBuffer(w, safeHTMLReader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if link.MFile != nil {
|
if link.MFile != nil {
|
||||||
defer link.MFile.Close()
|
defer link.MFile.Close()
|
||||||
attachHeader(w, file)
|
attachHeader(w, file)
|
||||||
@ -152,9 +80,7 @@ func Proxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.
|
|||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
for h, v := range res.Header {
|
maps.Copy(w.Header(), res.Header)
|
||||||
w.Header()[h] = v
|
|
||||||
}
|
|
||||||
w.WriteHeader(res.StatusCode)
|
w.WriteHeader(res.StatusCode)
|
||||||
if r.Method == http.MethodHead {
|
if r.Method == http.MethodHead {
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package handles
|
package handles
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
stdpath "path"
|
stdpath "path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
@ -15,7 +18,9 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/microcosm-cc/bluemonday"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/yuin/goldmark"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Down(c *gin.Context) {
|
func Down(c *gin.Context) {
|
||||||
@ -124,7 +129,34 @@ func localProxy(c *gin.Context, link *model.Link, file model.Obj, proxyRange boo
|
|||||||
if proxyRange {
|
if proxyRange {
|
||||||
common.ProxyRange(link, file.GetSize())
|
common.ProxyRange(link, file.GetSize())
|
||||||
}
|
}
|
||||||
err = common.Proxy(c.Writer, c.Request, link, file)
|
|
||||||
|
//优先处理md文件
|
||||||
|
if utils.Ext(file.GetName()) == "md" && setting.GetBool(conf.FilterReadMeScripts) {
|
||||||
|
w := c.Writer
|
||||||
|
buf := bytes.NewBuffer(make([]byte, 0, file.GetSize()))
|
||||||
|
err = common.Proxy(&proxyResponseWriter{ResponseWriter: w, Writer: buf}, c.Request, link, file)
|
||||||
|
if err == nil && buf.Len() > 0 {
|
||||||
|
if w.Status() < 200 || w.Status() > 300 {
|
||||||
|
w.Write(buf.Bytes())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var html bytes.Buffer
|
||||||
|
if err = goldmark.Convert(buf.Bytes(), &html); err != nil {
|
||||||
|
err = fmt.Errorf("markdown conversion failed: %w", err)
|
||||||
|
} else {
|
||||||
|
buf.Reset()
|
||||||
|
err = bluemonday.UGCPolicy().SanitizeReaderToWriter(&html, buf)
|
||||||
|
if err == nil {
|
||||||
|
w.Header().Set("Content-Length", strconv.FormatInt(int64(buf.Len()), 10))
|
||||||
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
|
_, err = utils.CopyWithBuffer(c.Writer, buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = common.Proxy(c.Writer, c.Request, link, file)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
common.ErrorResp(c, err, 500, true)
|
common.ErrorResp(c, err, 500, true)
|
||||||
return
|
return
|
||||||
@ -150,3 +182,12 @@ func canProxy(storage driver.Driver, filename string) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type proxyResponseWriter struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pw *proxyResponseWriter) Write(p []byte) (int, error) {
|
||||||
|
return pw.Writer.Write(p)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user