add more checks
Marco Andronaco andronacomarco@gmail.com
Wed, 13 Nov 2024 18:34:23 +0100
1 files changed,
88 insertions(+),
32 deletions(-)
jump to
M
merge.go
→
merge.go
@@ -1,15 +1,23 @@
package main import ( + "errors" "fmt" "io" "net/http" "os" "os/exec" "strconv" - "strings" +) + +const ( + outputPath = "output.mp4" + audioPath = "temp_audio.opus" + videoPath = "temp_video.mp4" ) +var sem = make(chan struct{}, 1) // Semaforo con buffer 1 + func saveUploadedFile(file io.Reader, path string) error { out, err := os.Create(path) if err != nil {@@ -21,53 +29,87 @@ _, err = io.Copy(out, file)
return err } -func processHandler(w http.ResponseWriter, r *http.Request) { +// Funzione helper per restituire un errore di richiesta non valida +func badRequest(w http.ResponseWriter, reason string) error { + http.Error(w, reason, http.StatusBadRequest) + return errors.New(reason) +} + +// Funzione per leggere e validare i dati del form e salvare i file temporaneamente +func parseAndValidateForm(w http.ResponseWriter, r *http.Request) (skip, fade, delay, duration float64, err error) { if r.Method != http.MethodPost { - http.Error(w, "Metodo non supportato", http.StatusMethodNotAllowed) + err = badRequest(w, "Metodo non supportato") return } - // Parse del form per ottenere i file e gli altri parametri - if err := r.ParseMultipartForm(10 << 20); err != nil { - http.Error(w, "Errore parsing form", http.StatusBadRequest) + // Parsing del form + if err = r.ParseMultipartForm(10 << 20); err != nil { + err = badRequest(w, "Errore nel form") return } // Recupera i file audio e video - audioFile, _, err := r.FormFile("audioFile") + audioFile, audioHeader, err := r.FormFile("audioFile") if err != nil { - http.Error(w, "File audio mancante", http.StatusBadRequest) + err = badRequest(w, "File audio mancante") return } defer audioFile.Close() - videoFile, _, err := r.FormFile("videoFile") + videoFile, videoHeader, err := r.FormFile("videoFile") if err != nil { - http.Error(w, "File video mancante", http.StatusBadRequest) + err = badRequest(w, "File video mancante") return } defer videoFile.Close() - // Salva i file temporaneamente - audioPath := "temp_audio.opus" - videoPath := "temp_video.mp4" - outputPath := "output.mp4" + // Controllo delle dimensioni dei file + const maxFileSize = 100 << 20 // 100 MB + if audioHeader.Size > maxFileSize { + err = badRequest(w, "File audio troppo grande") + return + } + if videoHeader.Size > maxFileSize { + err = badRequest(w, "File video troppo grande") + return + } - if err := saveUploadedFile(audioFile, audioPath); err != nil { + // Recupera e valida i parametri dal form + if skip, err = strconv.ParseFloat(r.FormValue("skip"), 64); err != nil || skip < 0 { + err = badRequest(w, "Parametro skip non valido") + return + } + + if fade, err = strconv.ParseFloat(r.FormValue("fade"), 64); err != nil || fade < 0 { + err = badRequest(w, "Parametro fade non valido") + return + } + + if delay, err = strconv.ParseFloat(r.FormValue("delay"), 64); err != nil || delay < 0 { + err = badRequest(w, "Parametro delay non valido") + return + } + + if duration, err = strconv.ParseFloat(r.FormValue("duration"), 64); err != nil || duration <= 0 { + err = badRequest(w, "Parametro duration non valido") + return + } + + // Salva i file temporaneamente + if err = saveUploadedFile(audioFile, audioPath); err != nil { http.Error(w, "Errore nel salvataggio del file audio", http.StatusInternalServerError) return } - if err := saveUploadedFile(videoFile, videoPath); err != nil { + if err = saveUploadedFile(videoFile, videoPath); err != nil { http.Error(w, "Errore nel salvataggio del file video", http.StatusInternalServerError) return } - // Recupera i parametri di configurazione dal form - skip, _ := strconv.ParseFloat(r.FormValue("skip"), 64) - fade, _ := strconv.ParseFloat(r.FormValue("fade"), 64) - delay, _ := strconv.ParseFloat(r.FormValue("delay"), 64) - duration, _ := strconv.ParseFloat(r.FormValue("duration"), 64) + return +} +// Funzione per gestire il processamento multimediale +func processMedia(w http.ResponseWriter, skip, fade, delay, duration float64) error { // Conversione delay in millisecondi delayMs := int(delay * 1000) fadeOutStart := duration - fade@@ -94,35 +136,49 @@ }
// Esecuzione del comando ffmpeg cmd := exec.Command("ffmpeg", ffmpegCommand...) - println(strings.Join(ffmpegCommand, " ")) - cmd.Stderr = os.Stderr // Mostra eventuali errori in console + cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout if err := cmd.Run(); err != nil { - http.Error(w, "Errore durante l'esecuzione di ffmpeg", http.StatusInternalServerError) - return + return fmt.Errorf("errore durante l'esecuzione di ffmpeg: %v", err) } // Impostazioni per scaricare il file di output w.Header().Set("Content-Disposition", "attachment; filename=output.mp4") w.Header().Set("Content-Type", "video/mp4") + // Pulizia dei file temporanei + os.Remove(audioPath) + os.Remove(videoPath) + + return nil +} + +// Handler principale +func processHandler(w http.ResponseWriter, r *http.Request) { + sem <- struct{}{} + defer func() { <-sem }() // Rilascia il semaforo alla fine + + skip, fade, delay, duration, err := parseAndValidateForm(w, r) + if err != nil { + return // Gli errori vengono giĆ gestiti in parseAndValidateForm + } + + if err := processMedia(w, skip, fade, delay, duration); err != nil { + http.Error(w, "Errore durante il processamento multimediale", http.StatusInternalServerError) + return + } + // Restituisce il file output.mp4 in risposta outputFile, err := os.Open(outputPath) if err != nil { - http.Error(w, "Errore nell'apertura del file output", http.StatusInternalServerError) return } defer outputFile.Close() - _, err = io.Copy(w, outputFile) - if err != nil { - http.Error(w, "Errore durante la copia del file", http.StatusInternalServerError) + if _, err = io.Copy(w, outputFile); err != nil { return } - // Pulizia dei file temporanei - os.Remove(audioPath) - os.Remove(videoPath) os.Remove(outputPath) }