mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-11-25 19:37:41 +08:00
feat(upload): add optional system file filtering for uploads (#1634)
This commit is contained in:
@@ -177,6 +177,7 @@ func InitialSettings() []model.SettingItem {
|
||||
{Key: conf.ShareArchivePreview, Value: "false", Type: conf.TypeBool, Group: model.GLOBAL, Flag: model.PUBLIC},
|
||||
{Key: conf.ShareForceProxy, Value: "true", Type: conf.TypeBool, Group: model.GLOBAL, Flag: model.PRIVATE},
|
||||
{Key: conf.ShareSummaryContent, Value: "@{{creator}} shared {{#each files}}{{#if @first}}\"{{filename this}}\"{{/if}}{{#if @last}}{{#unless (eq @index 0)}} and {{@index}} more files{{/unless}}{{/if}}{{/each}} from {{site_title}}: {{base_url}}/@s/{{id}}{{#if pwd}} , the share code is {{pwd}}{{/if}}{{#if expires}}, please access before {{dateLocaleString expires}}.{{/if}}", Type: conf.TypeText, Group: model.GLOBAL, Flag: model.PUBLIC},
|
||||
{Key: conf.IgnoreSystemFiles, Value: "false", Type: conf.TypeBool, Group: model.GLOBAL, Flag: model.PRIVATE, Help: `When enabled, ignores common system files during upload (.DS_Store, desktop.ini, Thumbs.db, and files starting with ._)`},
|
||||
|
||||
// single settings
|
||||
{Key: conf.Token, Value: token, Type: conf.TypeString, Group: model.SINGLE, Flag: model.PRIVATE},
|
||||
|
||||
@@ -56,6 +56,7 @@ const (
|
||||
ShareArchivePreview = "share_archive_preview"
|
||||
ShareForceProxy = "share_force_proxy"
|
||||
ShareSummaryContent = "share_summary_content"
|
||||
IgnoreSystemFiles = "ignore_system_files"
|
||||
|
||||
// index
|
||||
SearchIndex = "search_index"
|
||||
|
||||
@@ -11,6 +11,7 @@ var (
|
||||
ObjectAlreadyExists = errors.New("object already exists")
|
||||
NotFolder = errors.New("not a folder")
|
||||
NotFile = errors.New("not a file")
|
||||
IgnoredSystemFile = errors.New("system file upload ignored")
|
||||
)
|
||||
|
||||
func IsObjectNotFound(err error) bool {
|
||||
|
||||
@@ -185,3 +185,20 @@ const (
|
||||
GB
|
||||
TB
|
||||
)
|
||||
|
||||
// IsSystemFile checks if a filename is a common system file that should be ignored
|
||||
// Returns true for files like .DS_Store, desktop.ini, Thumbs.db, and Apple Double files (._*)
|
||||
func IsSystemFile(filename string) bool {
|
||||
// Common system files
|
||||
switch filename {
|
||||
case ".DS_Store", "desktop.ini", "Thumbs.db":
|
||||
return true
|
||||
}
|
||||
|
||||
// Apple Double files (._*)
|
||||
if strings.HasPrefix(filename, "._") {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
42
pkg/utils/file_test.go
Normal file
42
pkg/utils/file_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsSystemFile(t *testing.T) {
|
||||
testCases := []struct {
|
||||
filename string
|
||||
expected bool
|
||||
}{
|
||||
// System files that should be filtered
|
||||
{".DS_Store", true},
|
||||
{"desktop.ini", true},
|
||||
{"Thumbs.db", true},
|
||||
{"._test.txt", true},
|
||||
{"._", true},
|
||||
{"._somefile", true},
|
||||
{"._folder_name", true},
|
||||
|
||||
// Regular files that should not be filtered
|
||||
{"test.txt", false},
|
||||
{"file.pdf", false},
|
||||
{"document.docx", false},
|
||||
{".gitignore", false},
|
||||
{".env", false},
|
||||
{"_underscore.txt", false},
|
||||
{"normal_file.txt", false},
|
||||
{"", false},
|
||||
{".hidden", false},
|
||||
{"..special", false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.filename, func(t *testing.T) {
|
||||
result := IsSystemFile(tc.filename)
|
||||
if result != tc.expected {
|
||||
t.Errorf("IsSystemFile(%q) = %v, want %v", tc.filename, result, tc.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ import (
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
ftpserver "github.com/fclairamb/ftpserverlib"
|
||||
"github.com/pkg/errors"
|
||||
@@ -49,6 +51,11 @@ func OpenUpload(ctx context.Context, path string, trunc bool) (*FileUploadProxy,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Check if system file should be ignored
|
||||
_, name := stdpath.Split(path)
|
||||
if setting.GetBool(conf.IgnoreSystemFiles) && utils.IsSystemFile(name) {
|
||||
return nil, errs.IgnoredSystemFile
|
||||
}
|
||||
tmpFile, err := os.CreateTemp(conf.Conf.TempDir, "file-*")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -150,6 +157,11 @@ func OpenUploadWithLength(ctx context.Context, path string, trunc bool, length i
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Check if system file should be ignored
|
||||
_, name := stdpath.Split(path)
|
||||
if setting.GetBool(conf.IgnoreSystemFiles) && utils.IsSystemFile(name) {
|
||||
return nil, errs.IgnoredSystemFile
|
||||
}
|
||||
if trunc {
|
||||
_ = fs.Remove(ctx, path)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/task"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
@@ -28,6 +30,14 @@ func getLastModified(c *gin.Context) time.Time {
|
||||
return lastModified
|
||||
}
|
||||
|
||||
// shouldIgnoreSystemFile checks if the filename should be ignored based on settings
|
||||
func shouldIgnoreSystemFile(filename string) bool {
|
||||
if setting.GetBool(conf.IgnoreSystemFiles) {
|
||||
return utils.IsSystemFile(filename)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func FsStream(c *gin.Context) {
|
||||
defer func() {
|
||||
if n, _ := io.ReadFull(c.Request.Body, []byte{0}); n == 1 {
|
||||
@@ -56,6 +66,11 @@ func FsStream(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
dir, name := stdpath.Split(path)
|
||||
// Check if system file should be ignored
|
||||
if shouldIgnoreSystemFile(name) {
|
||||
common.ErrorStrResp(c, errs.IgnoredSystemFile.Error(), 403)
|
||||
return
|
||||
}
|
||||
// 如果请求头 Content-Length 和 X-File-Size 都没有,则 size=-1,表示未知大小的流式上传
|
||||
size := c.Request.ContentLength
|
||||
if size < 0 {
|
||||
@@ -160,6 +175,11 @@ func FsForm(c *gin.Context) {
|
||||
}
|
||||
defer f.Close()
|
||||
dir, name := stdpath.Split(path)
|
||||
// Check if system file should be ignored
|
||||
if shouldIgnoreSystemFile(name) {
|
||||
common.ErrorStrResp(c, errs.IgnoredSystemFile.Error(), 403)
|
||||
return
|
||||
}
|
||||
h := make(map[*utils.HashType]string)
|
||||
if md5 := c.GetHeader("X-File-Md5"); md5 != "" {
|
||||
h[utils.MD5] = md5
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
@@ -286,6 +287,10 @@ func (b *s3Backend) PutObject(
|
||||
Modified: ti,
|
||||
Ctime: time.Now(),
|
||||
}
|
||||
// Check if system file should be ignored
|
||||
if setting.GetBool(conf.IgnoreSystemFiles) && utils.IsSystemFile(obj.Name) {
|
||||
return result, errs.IgnoredSystemFile
|
||||
}
|
||||
stream := &stream.FileStream{
|
||||
Obj: &obj,
|
||||
Reader: input,
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/net"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
@@ -358,6 +359,10 @@ func (h *Handler) handlePut(w http.ResponseWriter, r *http.Request) (status int,
|
||||
Modified: h.getModTime(r),
|
||||
Ctime: h.getCreateTime(r),
|
||||
}
|
||||
// Check if system file should be ignored
|
||||
if setting.GetBool(conf.IgnoreSystemFiles) && utils.IsSystemFile(obj.Name) {
|
||||
return http.StatusForbidden, errs.IgnoredSystemFile
|
||||
}
|
||||
fsStream := &stream.FileStream{
|
||||
Obj: &obj,
|
||||
Reader: r.Body,
|
||||
|
||||
Reference in New Issue
Block a user