diff --git a/tools/rest/uploaded_file.go b/tools/rest/uploaded_file.go index 74cae162..05050923 100644 --- a/tools/rest/uploaded_file.go +++ b/tools/rest/uploaded_file.go @@ -8,7 +8,9 @@ import ( "net/http" "path/filepath" "regexp" + "strings" + "github.com/pocketbase/pocketbase/tools/inflector" "github.com/pocketbase/pocketbase/tools/security" ) @@ -68,10 +70,29 @@ func FindUploadedFiles(r *http.Request, key string) ([]*UploadedFile, error) { return nil, err } - ext := extensionInvalidCharsRegex.ReplaceAllString(filepath.Ext(fh.Filename), "") + originalExt := filepath.Ext(fh.Filename) + sanitizedExt := extensionInvalidCharsRegex.ReplaceAllString(originalExt, "") + + originalName := strings.TrimSuffix(fh.Filename, originalExt) + sanitizedName := inflector.Snakecase(originalName) + + if length := len(sanitizedName); length < 3 { + // the name is too short so we concatenate an additional random part + sanitizedName += ("_" + security.RandomString(10)) + } else if length > 100 { + // keep only the first 100 characters (it is multibyte safe after Snakecase) + sanitizedName = sanitizedName[:100] + } + + uploadedFilename := fmt.Sprintf( + "%s_%s%s", + sanitizedName, + security.RandomString(10), // ensure that there is always a random part + sanitizedExt, + ) result[i] = &UploadedFile{ - name: fmt.Sprintf("%s%s", security.RandomString(32), ext), + name: uploadedFilename, header: fh, bytes: buf.Bytes(), } diff --git a/tools/rest/uploaded_file_test.go b/tools/rest/uploaded_file_test.go index 7b5975b8..1bdb76d1 100644 --- a/tools/rest/uploaded_file_test.go +++ b/tools/rest/uploaded_file_test.go @@ -14,8 +14,8 @@ import ( ) func TestFindUploadedFiles(t *testing.T) { - // create a test temporary file - tmpFile, err := os.CreateTemp(os.TempDir(), "tmpfile-*.txt") + // create a test temporary file (with very large prefix to test if it will be truncated) + tmpFile, err := os.CreateTemp(os.TempDir(), strings.Repeat("a", 150)+"tmpfile-*.txt") if err != nil { t.Fatal(err) } @@ -57,7 +57,11 @@ func TestFindUploadedFiles(t *testing.T) { } if !strings.HasSuffix(result[0].Name(), ".txt") { - t.Fatalf("Expected the file name to have suffix .txt - %v", result[0].Name()) + t.Fatalf("Expected the file name to have suffix .txt, got %v", result[0].Name()) + } + + if length := len(result[0].Name()); length != 115 { // truncated + random part + ext + t.Fatalf("Expected the file name to have length of 115, got %d\n%q", length, result[0].Name()) } if string(result[0].Bytes()) != "test" {