fix(05): CR-01 serve thumb URLs from the validated path key
This commit is contained in:
@@ -10,9 +10,10 @@ import (
|
||||
|
||||
const defaultStaticContentType = "application/octet-stream"
|
||||
|
||||
// StaticHandler serves GET prefix/<partition>/<disk_name> from bucket.
|
||||
// The blob key is rebuilt from disk_name via PartitionDirectory; request
|
||||
// path segments never reach NewReader unvalidated (T-05-13).
|
||||
// StaticHandler serves GET prefix/<partition>/<filename> from bucket.
|
||||
// filename is the original disk_name or a thumb_* sibling stored in the
|
||||
// original's partition. The blob key is the validated 4-segment path;
|
||||
// unvalidated request segments never reach NewReader (T-05-13).
|
||||
func StaticHandler(bucket *blob.Bucket, prefix string) http.Handler {
|
||||
prefix = strings.TrimSuffix(prefix, "/")
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -29,12 +30,11 @@ func StaticHandler(bucket *blob.Bucket, prefix string) http.Handler {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
diskName, ok := parsePublicBlobPath(rel)
|
||||
key, ok := parsePublicBlobPath(rel)
|
||||
if !ok {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
key := BlobKey(diskName)
|
||||
reader, err := bucket.NewReader(r.Context(), key, nil)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
@@ -66,10 +66,13 @@ func stripStaticPrefix(path, prefix string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// parsePublicBlobPath accepts exactly 3 partition groups plus disk_name
|
||||
// whose PartitionDirectory matches those groups. Rejects "..", empty
|
||||
// segments, extra slashes, and mismatched partitions.
|
||||
func parsePublicBlobPath(p string) (string, bool) {
|
||||
// parsePublicBlobPath accepts exactly 3 partition groups plus a filename
|
||||
// and returns that path as the blob key. Originals must live in
|
||||
// PartitionDirectory(filename); thumb_* names are stored beside the
|
||||
// original, so their partition is not derived from the thumb filename.
|
||||
// Rejects "..", empty segments, extra slashes, and mismatched original
|
||||
// partitions.
|
||||
func parsePublicBlobPath(p string) (key string, ok bool) {
|
||||
if p == "" || strings.Contains(p, "\\") || strings.Contains(p, "..") || strings.Contains(p, "//") {
|
||||
return "", false
|
||||
}
|
||||
@@ -82,11 +85,13 @@ func parsePublicBlobPath(p string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
diskName := parts[3]
|
||||
filename := parts[3]
|
||||
got := strings.Join(parts[:3], "/")
|
||||
want := strings.TrimSuffix(PartitionDirectory(diskName), "/")
|
||||
if got != want {
|
||||
return "", false
|
||||
if !strings.HasPrefix(filename, "thumb_") {
|
||||
want := strings.TrimSuffix(PartitionDirectory(filename), "/")
|
||||
if got != want {
|
||||
return "", false
|
||||
}
|
||||
}
|
||||
return diskName, true
|
||||
return got + "/" + filename, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user