include-upload-local.go (1740B)
1 package main 2 3 import ( 4 "fmt" 5 "net/http" 6 "os" 7 "path/filepath" 8 "strings" 9 ) 10 11 func localFileHandler(w http.ResponseWriter, r *http.Request) { 12 if r.Method != http.MethodPost { 13 http.Redirect(w, r, "/upload", http.StatusSeeOther) 14 return 15 } 16 17 rawPath := strings.TrimSpace(r.FormValue("filepath")) 18 if rawPath == "" { 19 renderError(w, "No file path provided", http.StatusBadRequest) 20 return 21 } 22 23 // Resolve to an absolute, cleaned path to prevent traversal tricks 24 absPath, err := filepath.Abs(rawPath) 25 if err != nil { 26 renderError(w, "Invalid file path", http.StatusBadRequest) 27 return 28 } 29 30 // Confirm the file actually exists and is a regular file (not a dir/symlink) 31 info, err := os.Stat(absPath) 32 if err != nil { 33 if os.IsNotExist(err) { 34 renderError(w, fmt.Sprintf("File not found: %s", absPath), http.StatusBadRequest) 35 } else { 36 renderError(w, fmt.Sprintf("Cannot access file: %v", err), http.StatusInternalServerError) 37 } 38 return 39 } 40 if !info.Mode().IsRegular() { 41 renderError(w, "Path must point to a regular file", http.StatusBadRequest) 42 return 43 } 44 45 f, err := os.Open(absPath) 46 if err != nil { 47 renderError(w, fmt.Sprintf("Failed to open file: %v", err), http.StatusInternalServerError) 48 return 49 } 50 defer f.Close() 51 52 deleteSource := r.FormValue("delete_source") == "on" 53 54 id, warningMsg, err := processUpload(f, filepath.Base(absPath)) 55 if err != nil { 56 renderError(w, err.Error(), http.StatusInternalServerError) 57 return 58 } 59 60 if deleteSource { 61 f.Close() 62 if removeErr := os.Remove(absPath); removeErr != nil { 63 warningMsg = strings.TrimPrefix(fmt.Sprintf("%s; could not delete source file: %v", warningMsg, removeErr), "; ") 64 } 65 } 66 67 redirectWithWarning(w, r, fmt.Sprintf("/file/%d", id), warningMsg) 68 }