Compare commits

..

2 commits

Author SHA1 Message Date
041922ea6d cleanupOldFiles: Diese Funktion durchsucht das Upload-Verzeichnis und löscht Dateien, die älter als 48 Stunden sind.
startCleanupProcess: Ein Hintergrundprozess, der cleanupOldFiles jede Stunde ausführt, um alte Dateien zu entfernen.
fileLifetime: Die Lebensdauer der Dateien ist auf 48 Stunden gesetzt. Dateien, die älter sind, werden gelöscht.
2024-09-02 15:01:39 +02:00
8bcfea0395 force_upload overwrite files 2024-09-02 14:56:51 +02:00

View file

@ -23,7 +23,16 @@ var (
uploadInterval = 10 * time.Second uploadInterval = 10 * time.Second
) )
const (
uploadDir = "./uploads"
cleanupInterval = 1 * time.Hour
fileLifetime = 48 * time.Hour
)
func main() { func main() {
// Starten Sie den Hintergrundprozess zum Löschen alter Dateien
go startCleanupProcess()
http.HandleFunc("/", homeHandler) http.HandleFunc("/", homeHandler)
http.HandleFunc("/upload", uploadHandler) http.HandleFunc("/upload", uploadHandler)
http.HandleFunc("/image/", imageHandler) http.HandleFunc("/image/", imageHandler)
@ -36,6 +45,39 @@ func main() {
http.ListenAndServe(":8080", nil) http.ListenAndServe(":8080", nil)
} }
func startCleanupProcess() {
ticker := time.NewTicker(cleanupInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
cleanupOldFiles()
}
}
}
func cleanupOldFiles() {
now := time.Now()
err := filepath.Walk(uploadDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && now.Sub(info.ModTime()) > fileLifetime {
err := os.Remove(path)
if err != nil {
log.Printf("Fehler beim Löschen der Datei %s: %v", path, err)
} else {
log.Printf("Datei gelöscht: %s", path)
}
}
return nil
})
if err != nil {
log.Printf("Fehler beim Durchsuchen des Verzeichnisses: %v", err)
}
}
func homeHandler(w http.ResponseWriter, r *http.Request) { func homeHandler(w http.ResponseWriter, r *http.Request) {
// Setzen der Content Security Policy // Setzen der Content Security Policy
w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';") w.Header().Set("Content-Security-Policy", "default-src 'self'; script-src 'self'; object-src 'none';")
@ -70,15 +112,12 @@ func generateNonce() (string, error) {
func uploadHandler(w http.ResponseWriter, r *http.Request) { func uploadHandler(w http.ResponseWriter, r *http.Request) {
nonce, err := generateNonce() nonce, err := generateNonce()
if err != nil { if err != nil {
// Fehlerbehandlung, z.B. Senden eines Serverfehlers
http.Error(w, "Serverfehler", http.StatusInternalServerError) http.Error(w, "Serverfehler", http.StatusInternalServerError)
log.Printf("Fehler beim Generieren des Nonce: %v", err) log.Printf("Fehler beim Generieren des Nonce: %v", err)
return return
} }
// Setzen der Content Security Policy
w.Header().Set("Content-Security-Policy", fmt.Sprintf("script-src 'self' 'nonce-%s';", nonce)) w.Header().Set("Content-Security-Policy", fmt.Sprintf("script-src 'self' 'nonce-%s';", nonce))
mu.Lock() mu.Lock()
defer mu.Unlock() defer mu.Unlock()
@ -97,8 +136,7 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
} }
defer file.Close() defer file.Close()
// Überprüfen Sie den MIME-Typ der Datei buffer := make([]byte, 512)
buffer := make([]byte, 512) // Genug für die Erkennung des MIME-Typs
_, err = file.Read(buffer) _, err = file.Read(buffer)
if err != nil { if err != nil {
http.Error(w, "Fehler beim Lesen der Datei", http.StatusInternalServerError) http.Error(w, "Fehler beim Lesen der Datei", http.StatusInternalServerError)
@ -106,14 +144,11 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
forceUpload := r.FormValue("force_upload") mimeType := http.DetectContentType(buffer)
if forceUpload != "true" { if !strings.HasPrefix(mimeType, "image/") && !strings.HasPrefix(mimeType, "text/xml") && !strings.HasPrefix(mimeType, "image/svg+xml") {
mimeType := http.DetectContentType(buffer) http.Error(w, "Nur Bild-Uploads sind erlaubt", http.StatusBadRequest)
if !strings.HasPrefix(mimeType, "image/") && !strings.HasPrefix(mimeType, "text/xml") && !strings.HasPrefix(mimeType, "image/svg+xml") { log.Printf("Versuch, eine Nicht-Bild-Datei hochzuladen: %v", mimeType)
http.Error(w, "Nur Bild-Uploads sind erlaubt", http.StatusBadRequest) return
log.Printf("Versuch, eine Nicht-Bild-Datei hochzuladen: %v", mimeType)
return
}
} }
_, err = file.Seek(0, io.SeekStart) _, err = file.Seek(0, io.SeekStart)
@ -123,23 +158,26 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
// Ermitteln, ob der ursprüngliche Dateiname erzwungen werden soll forceUpload := r.FormValue("force_upload")
//forceName := r.Header.Get("Force-Name")
forceName := r.FormValue("force_name") forceName := r.FormValue("force_name")
var filename string var filename string
if forceName == "true" { if forceName == "true" {
filename = handler.Filename filename = handler.Filename
} else { } else {
// Extrahiere nur die Dateiendung
fileExtension := filepath.Ext(handler.Filename) fileExtension := filepath.Ext(handler.Filename)
// Zeitstempel zum Dateinamen hinzufügen
timestamp := time.Now().Format("20060102-150405") timestamp := time.Now().Format("20060102-150405")
filename = fmt.Sprintf("%s%s", timestamp, fileExtension) filename = fmt.Sprintf("%s%s", timestamp, fileExtension)
} }
// Datei speichern
uploadPath := "./uploads/" + filename uploadPath := "./uploads/" + filename
if _, err := os.Stat(uploadPath); err == nil && forceUpload != "true" {
http.Error(w, "Datei existiert bereits. Überschreiben nicht erlaubt.", http.StatusConflict)
log.Printf("Versuch, bestehende Datei ohne force_upload zu überschreiben: %v", filename)
return
}
f, err := os.Create(uploadPath) f, err := os.Create(uploadPath)
if err != nil { if err != nil {
http.Error(w, "Fehler beim Erstellen der Datei", http.StatusInternalServerError) http.Error(w, "Fehler beim Erstellen der Datei", http.StatusInternalServerError)
@ -155,18 +193,13 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
lastUploadTime = time.Now() // Setzen Sie die Zeit des letzten Uploads lastUploadTime = time.Now()
// Vor dem Template-Rendering prüfen, ob eine JSON-Antwort erwartet wird
responseType := r.URL.Query().Get("responseType") responseType := r.URL.Query().Get("responseType")
if responseType == "json" { if responseType == "json" {
jsonResponse(w, nonce, filename) jsonResponse(w, nonce, filename)
return return
} }
// Template-Rendering-Logik, wenn keine JSON-Antwort erwartet wird
renderTemplate(w, nonce, filename) renderTemplate(w, nonce, filename)
} else { } else {
tmpl, err := template.ParseFiles("templates/uploadForm.html") tmpl, err := template.ParseFiles("templates/uploadForm.html")
if err != nil { if err != nil {
@ -174,12 +207,10 @@ func uploadHandler(w http.ResponseWriter, r *http.Request) {
log.Printf("Fehler beim Laden des Templates: %v", err) log.Printf("Fehler beim Laden des Templates: %v", err)
return return
} }
err = tmpl.Execute(w, nil) err = tmpl.Execute(w, nil)
if err != nil { if err != nil {
http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError) http.Error(w, "Fehler beim Rendern des Templates", http.StatusInternalServerError)
log.Printf("Fehler beim Rendern des Templates: %v", err) log.Printf("Fehler beim Rendern des Templates: %v", err)
return
} }
} }
} }