mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 22:37:28 +00:00
fix(files): encode download filenames (#91)
Co-authored-by: rissrice2105-agent <rissrice2105-agent@users.noreply.github.com>
This commit is contained in:
parent
21630c2d17
commit
b777bd72e8
2 changed files with 42 additions and 1 deletions
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
@ -224,7 +225,9 @@ func (h *webSrv) handleDownload(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
w.Header().Set("Content-Disposition", "attachment; filename=\""+path.Base(vpath)+"\"")
|
w.Header().Set("Content-Disposition", mime.FormatMediaType("attachment", map[string]string{
|
||||||
|
"filename": path.Base(vpath),
|
||||||
|
}))
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
w.Header().Set("Content-Type", "application/octet-stream")
|
||||||
w.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))
|
w.Header().Set("Content-Length", strconv.FormatInt(fi.Size(), 10))
|
||||||
_, _ = io.Copy(w, f)
|
_, _ = io.Copy(w, f)
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ package files
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
|
"mime"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -124,6 +127,41 @@ func TestWebRoundTrip(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebDownloadEncodesUnicodeFilename(t *testing.T) {
|
||||||
|
svc, _, u := newTestService(t)
|
||||||
|
h := svc.WebHandler(WebConfig{
|
||||||
|
Title: "files.test",
|
||||||
|
Authenticate: func(user, pass string) (store.User, bool, error) {
|
||||||
|
return u, user == "alice" && pass == "secret", nil
|
||||||
|
},
|
||||||
|
})
|
||||||
|
cookie := loginCookie(t, h)
|
||||||
|
name := "résumé.txt"
|
||||||
|
if _, _, err := svc.OpenFor(u.Name); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(filepath.Join(svc.privRoot(u.Name), name), []byte("complete"), 0o644); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rr := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/download?path="+url.QueryEscape("/me/"+name), nil)
|
||||||
|
req.AddCookie(cookie)
|
||||||
|
h.ServeHTTP(rr, req)
|
||||||
|
|
||||||
|
disposition := rr.Header().Get("Content-Disposition")
|
||||||
|
if !strings.Contains(disposition, "filename*=") {
|
||||||
|
t.Fatalf("Content-Disposition should encode a Unicode filename: %q", disposition)
|
||||||
|
}
|
||||||
|
mediaType, params, err := mime.ParseMediaType(disposition)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("invalid Content-Disposition: %v", err)
|
||||||
|
}
|
||||||
|
if mediaType != "attachment" || params["filename"] != name {
|
||||||
|
t.Fatalf("Content-Disposition filename: got %q, want %q", params["filename"], name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWebMutationsRejectGet(t *testing.T) {
|
func TestWebMutationsRejectGet(t *testing.T) {
|
||||||
h, _ := webTestHandler(t)
|
h, _ := webTestHandler(t)
|
||||||
cookie := loginCookie(t, h)
|
cookie := loginCookie(t, h)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue