mirror of https://github.com/cloudreve/Cloudreve
fix(es): redact non-ASCII file name in `filename` segment (#2473)
parent
8d6d188c3f
commit
633ea479d7
|
@ -166,6 +166,21 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// toASCIISafeFilename converts a filename to ASCII-safe version by replacing
|
||||||
|
// non-ASCII characters and special characters with underscores.
|
||||||
|
// This is used for the fallback filename parameter in Content-Disposition header.
|
||||||
|
func toASCIISafeFilename(filename string) string {
|
||||||
|
asciiFilename := ""
|
||||||
|
for _, r := range filename {
|
||||||
|
if r <= 127 && r >= 32 && r != '"' && r != '\\' {
|
||||||
|
asciiFilename += string(r)
|
||||||
|
} else {
|
||||||
|
asciiFilename += "_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return asciiFilename
|
||||||
|
}
|
||||||
|
|
||||||
// NewEntitySource creates a new EntitySource.
|
// NewEntitySource creates a new EntitySource.
|
||||||
func NewEntitySource(
|
func NewEntitySource(
|
||||||
e fs.Entity,
|
e fs.Entity,
|
||||||
|
@ -249,9 +264,21 @@ func (f *entitySource) Serve(w http.ResponseWriter, r *http.Request, opts ...Ent
|
||||||
w.Header().Set("Etag", "\""+hashid.EncodeEntityID(f.hasher, f.e.ID())+"\"")
|
w.Header().Set("Etag", "\""+hashid.EncodeEntityID(f.hasher, f.e.ID())+"\"")
|
||||||
|
|
||||||
if f.o.IsDownload {
|
if f.o.IsDownload {
|
||||||
encodedFilename := url.PathEscape(f.o.DisplayName)
|
// Properly handle non-ASCII characters in filename according to RFC 6266
|
||||||
|
displayName := f.o.DisplayName
|
||||||
|
asciiFilename := toASCIISafeFilename(displayName)
|
||||||
|
|
||||||
|
// RFC 6266 compliant filename* encoding
|
||||||
|
encodedFilename := url.QueryEscape(displayName)
|
||||||
|
|
||||||
|
if displayName == asciiFilename {
|
||||||
|
// Filename contains only ASCII characters, use simple form
|
||||||
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", displayName))
|
||||||
|
} else {
|
||||||
|
// Filename contains non-ASCII characters, use both parameters
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s",
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"; filename*=UTF-8''%s",
|
||||||
f.o.DisplayName, encodedFilename))
|
asciiFilename, encodedFilename))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done, rangeReq := checkPreconditions(w, r, etag)
|
done, rangeReq := checkPreconditions(w, r, etag)
|
||||||
|
|
Loading…
Reference in New Issue