From e767eaf7e5b53dbdda8a8e882d521fd4e7175571 Mon Sep 17 00:00:00 2001 From: odrling Date: Mon, 15 Jul 2024 14:44:34 +0200 Subject: [PATCH] set utf-8 encoded filenames Characters in HTTP headers should be encoded with the ISO 8859-1 character set. So the previous implementation was wrong. Browsers may have slightly different behaviours but this seems to work in firefox. --- server/files.go | 7 ++++--- server/producer_test.go | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/server/files.go b/server/files.go index 7199de7..bb797f4 100644 --- a/server/files.go +++ b/server/files.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "mime/multipart" + "net/url" "strconv" "strings" @@ -128,7 +129,7 @@ func Download(ctx context.Context, input *DownloadInput) (*huma.StreamResponse, writer := ctx.BodyWriter() stat, err := obj.Stat() - filename := stat.UserMetadata["Filename"] + filename := url.PathEscape(stat.UserMetadata["Filename"]) content_type := stat.UserMetadata["Type"] main_type, _, _ := strings.Cut(content_type, "/") @@ -136,9 +137,9 @@ func Download(ctx context.Context, input *DownloadInput) (*huma.StreamResponse, ctx.SetHeader("Accept-Range", "bytes") ctx.SetHeader("Content-Length", fmt.Sprintf("%d", stat.Size)) if main_type == "text" { - ctx.SetHeader("Content-Disposition", fmt.Sprintf("inline; filename=%s", filename)) + ctx.SetHeader("Content-Disposition", fmt.Sprintf("inline; filename=\"%s\"; filename*=UTF-8''%s", filename, filename)) } else { - ctx.SetHeader("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename)) + ctx.SetHeader("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s", filename, filename)) } ctx.SetHeader("Content-Type", content_type) diff --git a/server/producer_test.go b/server/producer_test.go index 4f87217..8093125 100644 --- a/server/producer_test.go +++ b/server/producer_test.go @@ -8,6 +8,7 @@ import ( "fmt" "mime/multipart" "net/http/httptest" + "net/url" "regexp" "testing" @@ -63,7 +64,7 @@ func TestUploadDownload(t *testing.T) { test_data := []byte("hello world") mime := mimetype.Detect(test_data) - filename := "test_file" + filename := "test file" upload_data := uploadData(t, api, test_data, filename) path := fmt.Sprintf("/%s", upload_data.Body.ID) @@ -96,7 +97,7 @@ func TestUploadDownload(t *testing.T) { } matched, _ := regexp.MatchString( - fmt.Sprintf("filename=%s", regexp.QuoteMeta(filename)), + fmt.Sprintf("filename=\"%s\"", regexp.QuoteMeta(url.PathEscape(filename))), content_disposition_header, )