feat: support folder uploads and sanitize upload paths
- Implement `cleanUploadDisplayName` in the backend to safely sanitize uploaded file paths, preserving directory structures while stripping unsafe characters and preventing path traversal. - Add folder upload capability in the frontend using the Directory Picker API. - Implement desktop notifications for completed uploads.
This commit is contained in:
@@ -16,6 +16,7 @@ import (
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -452,7 +453,7 @@ func (s *UploadService) writeIncomingFilesToBox(ctx context.Context, box *Box, f
|
||||
|
||||
box.Files = append(box.Files, File{
|
||||
ID: fileID,
|
||||
Name: filepath.Base(incoming.Name()),
|
||||
Name: cleanUploadDisplayName(incoming.Name()),
|
||||
StoredName: storedName,
|
||||
Size: incoming.Size(),
|
||||
ContentType: contentType,
|
||||
@@ -464,6 +465,36 @@ func (s *UploadService) writeIncomingFilesToBox(ctx context.Context, box *Box, f
|
||||
return nil
|
||||
}
|
||||
|
||||
func cleanUploadDisplayName(name string) string {
|
||||
clean := strings.TrimSpace(strings.ReplaceAll(name, "\\", "/"))
|
||||
clean = strings.TrimLeft(clean, "/")
|
||||
clean = path.Clean(clean)
|
||||
if clean == "." || clean == "/" || clean == "" {
|
||||
return "download"
|
||||
}
|
||||
parts := strings.Split(clean, "/")
|
||||
safeParts := make([]string, 0, len(parts))
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" || part == "." || part == ".." {
|
||||
continue
|
||||
}
|
||||
part = strings.Map(func(r rune) rune {
|
||||
if r < 0x20 || r == 0x7f || r == '/' || r == '\\' {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}, part)
|
||||
if part != "" {
|
||||
safeParts = append(safeParts, part)
|
||||
}
|
||||
}
|
||||
if len(safeParts) == 0 {
|
||||
return "download"
|
||||
}
|
||||
return strings.Join(safeParts, "/")
|
||||
}
|
||||
|
||||
func (s *UploadService) GetBox(id string) (Box, error) {
|
||||
var box Box
|
||||
err := s.db.View(func(tx *bbolt.Tx) error {
|
||||
|
||||
Reference in New Issue
Block a user