From d139501dd47e2f8e4fe147ca2113b6f61263e258 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sun, 31 May 2026 22:27:04 -0700 Subject: [PATCH] Implement strict RFC 5987 header encoding to fix Next.js proxy crash --- backend/handlers/files.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/backend/handlers/files.go b/backend/handlers/files.go index 43cf7b0..9820ba3 100644 --- a/backend/handlers/files.go +++ b/backend/handlers/files.go @@ -1028,8 +1028,29 @@ func (h *FSHandler) Download(c *fiber.Ctx) error { c.Set("Accept-Ranges", "bytes") c.Set("Content-Type", mime.TypeByExtension(filepath.Ext(resolvedPath))) - safeNameQuote := strings.ReplaceAll(info.Name(), "\"", "\\\"") - encodedName := url.PathEscape(info.Name()) + // Ultra-safe fallback name: replace quotes and non-ASCII with underscore + safeNameBytes := make([]byte, 0, len(info.Name())) + for i := 0; i < len(info.Name()); i++ { + b := info.Name()[i] + if b >= 32 && b <= 126 && b != '"' && b != '\\' { + safeNameBytes = append(safeNameBytes, b) + } else { + safeNameBytes = append(safeNameBytes, '_') + } + } + safeNameQuote := string(safeNameBytes) + + // Strict RFC 5987 encoding for filename*= + var sb strings.Builder + for i := 0; i < len(info.Name()); i++ { + b := info.Name()[i] + if (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') || b == '.' || b == '-' || b == '_' || b == '~' { + sb.WriteByte(b) + } else { + sb.WriteString(fmt.Sprintf("%%%02X", b)) + } + } + encodedName := sb.String() if c.Query("download") == "true" { c.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s", safeNameQuote, encodedName))