package handlers import ( "net/http" "path/filepath" ) // ServeMedia serves media files with path traversal protection func (h *Handlers) ServeMedia(w http.ResponseWriter, r *http.Request) { // Expected path format: /api/media/{accountID}/{filename} path := r.URL.Path[len("/api/media/"):] // Split path into accountID and filename var accountID, filename string for i, ch := range path { if ch == '/' { accountID = path[:i] filename = path[i+1:] break } } if accountID == "" || filename == "" { http.Error(w, "Invalid media path", http.StatusBadRequest) return } // Construct full file path filePath := filepath.Join(h.config.Media.DataPath, accountID, filename) // Security check: ensure the resolved path is within the media directory mediaDir := filepath.Join(h.config.Media.DataPath, accountID) absFilePath, err := filepath.Abs(filePath) if err != nil { http.Error(w, "Invalid file path", http.StatusBadRequest) return } absMediaDir, err := filepath.Abs(mediaDir) if err != nil { http.Error(w, "Invalid media directory", http.StatusInternalServerError) return } // Check if file path is within media directory (prevent directory traversal) if len(absFilePath) < len(absMediaDir) || absFilePath[:len(absMediaDir)] != absMediaDir { http.Error(w, "Access denied", http.StatusForbidden) return } // Serve the file http.ServeFile(w, r, absFilePath) }