feat: validate image type on server-side upload
Ultraworked with Sisyphus (https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crussell/db"
|
||||
"crussell/internal/images"
|
||||
"crussell/internal/s3"
|
||||
"crussell/mw"
|
||||
"encoding/json"
|
||||
@@ -43,6 +44,7 @@ func processImage(data []byte, quality int) ([]byte, error) {
|
||||
}
|
||||
|
||||
// validateInputLength returns an error if input exceeds max length
|
||||
|
||||
func validateInputLength(input string) error {
|
||||
if len(input) > MaxInputLength {
|
||||
return fmt.Errorf("input exceeds maximum length of %d characters", MaxInputLength)
|
||||
@@ -339,7 +341,12 @@ func ListFilters(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(key, "filter[") && len(values) > 0 && values[0] != "" {
|
||||
category := strings.Trim(key, "[]")
|
||||
category = strings.TrimPrefix(category, "filter[")
|
||||
selectedCategories[category] = values[0]
|
||||
value := values[0]
|
||||
if len(category)+len(value)+1 > 256 {
|
||||
http.Error(w, "filter value too long", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
selectedCategories[category] = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +555,7 @@ func UploadImage(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
r.ParseMultipartForm(10 << 20)
|
||||
|
||||
file, header, err := r.FormFile("file")
|
||||
file, _, err := r.FormFile("file")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get file: %v", err)
|
||||
http.Error(w, "No file provided", http.StatusBadRequest)
|
||||
@@ -556,7 +563,7 @@ func UploadImage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
thumbFile, thumbHeader, err := r.FormFile("thumbnail")
|
||||
thumbFile, _, err := r.FormFile("thumbnail")
|
||||
if err != nil {
|
||||
log.Printf("Failed to get thumbnail: %v", err)
|
||||
http.Error(w, "No thumbnail provided", http.StatusBadRequest)
|
||||
@@ -573,30 +580,19 @@ func UploadImage(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Use nanosecond timestamp for unique keys
|
||||
timestamp := time.Now().UnixNano()
|
||||
|
||||
// Extract extension from main file
|
||||
mainExt := ".jpg"
|
||||
if idx := strings.LastIndex(header.Filename, "."); idx != -1 {
|
||||
mainExt = strings.ToLower(header.Filename[idx:])
|
||||
}
|
||||
|
||||
// Extract extension from thumbnail file
|
||||
thumbExt := ".jpg"
|
||||
if idx := strings.LastIndex(thumbHeader.Filename, "."); idx != -1 {
|
||||
thumbExt = strings.ToLower(thumbHeader.Filename[idx:])
|
||||
}
|
||||
|
||||
key := fmt.Sprintf("portfolio/%d%s", timestamp, mainExt)
|
||||
thumbKey := fmt.Sprintf("portfolio/%d_thumb%s", timestamp, thumbExt)
|
||||
|
||||
fileBytes, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
log.Printf("Failed to read file: %v", err)
|
||||
http.Error(w, "Failed to read file", http.StatusInternalServerError)
|
||||
http.Error(w, "Failed to read file", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
ext, err := images.ValidateImageBytes(fileBytes)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Images are already processed by frontend (compressed, metadata stripped)
|
||||
// Skip re-encoding - just use the uploaded bytes directly
|
||||
|
||||
@@ -607,6 +603,17 @@ func UploadImage(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
thumbExt, err := images.ValidateImageBytes(thumbBytes)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Use nanosecond timestamp for unique keys
|
||||
timestamp := time.Now().UnixNano()
|
||||
key := fmt.Sprintf("portfolio/%d%s", timestamp, ext)
|
||||
thumbKey := fmt.Sprintf("portfolio/%d_thumb%s", timestamp, thumbExt)
|
||||
|
||||
// Thumbnail is already processed by frontend - use as-is
|
||||
|
||||
bucket := "crussell"
|
||||
|
||||
Reference in New Issue
Block a user