feat: file_save_disk, file_delete, file_serve, upload_parse, upload_handler, thumbnail_generate (issue 0014 fase 3)
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
package infra
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FileDelete elimina un archivo del disco. Rechaza paths que contengan ".." para
|
||||
// evitar path traversal fuera del directorio esperado.
|
||||
//
|
||||
// Retorna error si el archivo no existe (os.ErrNotExist), si el path contiene "..",
|
||||
// o si la operacion de remove falla por permisos.
|
||||
func FileDelete(path string) error {
|
||||
if path == "" {
|
||||
return fmt.Errorf("file_delete: path vacio")
|
||||
}
|
||||
|
||||
// Rechazar cualquier path traversal explicito en el input original
|
||||
// (filepath.Clean resuelve `..` y borraria la huella, asi que comprobamos antes)
|
||||
if containsParentRef(path) {
|
||||
return fmt.Errorf("file_delete: path traversal no permitido en %q", path)
|
||||
}
|
||||
clean := filepath.Clean(path)
|
||||
|
||||
if _, err := os.Stat(clean); err != nil {
|
||||
return fmt.Errorf("file_delete: stat %s: %w", clean, err)
|
||||
}
|
||||
|
||||
if err := os.Remove(clean); err != nil {
|
||||
return fmt.Errorf("file_delete: remove %s: %w", clean, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// containsParentRef detecta si el path tiene un segmento ".." entre separadores.
|
||||
// Acepta tanto "/" como "\" como separadores. No marca como malo nombres como "..bashrc".
|
||||
func containsParentRef(path string) bool {
|
||||
// Normalizar a slashes
|
||||
p := strings.ReplaceAll(path, "\\", "/")
|
||||
for _, seg := range strings.Split(p, "/") {
|
||||
if seg == ".." {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user