commit 85150634f83d0d1754ce7b6ed43746cb05b9ad33 Author: gman Date: Fri Mar 15 07:22:34 2024 -0700 Upload files to "/" diff --git a/server.go b/server.go new file mode 100644 index 0000000..d62b32d --- /dev/null +++ b/server.go @@ -0,0 +1,363 @@ +package main + +import ( + + "bufio" + "errors" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "io/ioutil" + "strings" +) + +const mediaDir = "media/" + +func LoadServersFromFile(filename string) ([]string, error) { + // Open the text file for reading + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + // Create a slice to store IP addresses + var ips []string + + // Create a scanner to read the file line by line + scanner := bufio.NewScanner(file) + for scanner.Scan() { + // Extract the IP from the line + ip := scanner.Text() + + // Append the IP address to the slice + ips = append(ips, ip) + } + + // Check for any errors during scanning + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading file: %w", err) + } + + return ips, nil +} + +func AddServerToFile(filename, ip string) error { + // Open the text file for appending + file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer file.Close() + + // Write the new IP to the file + _, err = fmt.Fprintln(file, ip) + if err != nil { + return err + } + + return nil +} + +func getRoot(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got / request\n") + io.WriteString(w, "This is my website!\n") +} +func getHello(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got /hello request\n") + io.WriteString(w, "Hello, HTTP!\n") +} +func getData(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got /data request\n") + // Set the content type header + w.Header().Set("Content-Type", "application/json") + + // Write your data to the response writer + // Here we're just returning a simple JSON response + io.WriteString(w, `{"message": "Hello, this is your data!"}`) +} +func getIPs(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got /ips request\n") + // Set the content type header + w.Header().Set("Content-Type", "text/plain") + + // Load IPs from file + ips, err := LoadServersFromFile("servers.txt") + if err != nil { + http.Error(w, fmt.Sprintf("Error loading IPs: %s", err), http.StatusInternalServerError) + return + } + + // Write IPs to the response writer separated by newline + for _, ip := range ips { + io.WriteString(w, ip+"\n") + } +} +func addIP(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got /addip request\n") + // Check if the request method is POST + if r.Method != http.MethodPost { + http.Error(w, "Only POST requests are allowed", http.StatusMethodNotAllowed) + return + } + + // Parse the IP address from the request body + ip := r.FormValue("ip") + if ip == "" { + http.Error(w, "IP address is required", http.StatusBadRequest) + return + } + + // Add the IP address to the file + err := AddServerToFile("servers.txt", ip) + if err != nil { + http.Error(w, fmt.Sprintf("Error adding IP: %s", err), http.StatusInternalServerError) + return + } + + // Respond with a success message + io.WriteString(w, "IP address added successfully\n") +} +func RemoveIPFromFile(filename, ipToRemove string) error { + // Open the original file for reading + file, err := os.Open(filename) + if err != nil { + return err + } + defer file.Close() + + // Create a new file to store the updated IP addresses + newFilename := filename + ".tmp" + newFile, err := os.Create(newFilename) + if err != nil { + return err + } + defer newFile.Close() + + // Create a scanner to read the file line by line + scanner := bufio.NewScanner(file) + for scanner.Scan() { + // Extract the IP from the line + ip := scanner.Text() + + // Check if the IP matches the one to remove + if ip != ipToRemove { + // Write the IP to the new file + _, err := fmt.Fprintln(newFile, ip) + if err != nil { + return err + } + } + } + + // Check for any errors during scanning + if err := scanner.Err(); err != nil { + return fmt.Errorf("error reading file: %w", err) + } + + // Close the new file + if err := newFile.Close(); err != nil { + return err + } + + // Replace the original file with the new file + if err := os.Rename(newFilename, filename); err != nil { + return err + } + + return nil +} + +func removeIP(w http.ResponseWriter, r *http.Request) { + fmt.Printf("got /removeip request\n") + // Check if the request method is POST + if r.Method != http.MethodPost { + http.Error(w, "Only POST requests are allowed", http.StatusMethodNotAllowed) + return + } + + // Parse the IP address from the request body + ip := r.FormValue("ip") + if ip == "" { + http.Error(w, "IP address is required", http.StatusBadRequest) + return + } + + // Remove the IP address from the file + err := RemoveIPFromFile("servers.txt", ip) + if err != nil { + http.Error(w, fmt.Sprintf("Error removing IP: %s", err), http.StatusInternalServerError) + return + } + + // Respond with a success message + io.WriteString(w, "IP address removed successfully\n") +} + +func uploadFileHandler(w http.ResponseWriter, r *http.Request) { + // Parse the multipart form + err := r.ParseMultipartForm(10 << 20) // 10 MB limit + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // Get the file from the form + file, handler, err := r.FormFile("file") + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + defer file.Close() + + // Get the path from the form or set a default path + path := r.FormValue("path") + if path == "" { + path = mediaDir + handler.Filename // Default path + } else { + path = mediaDir + path + } + + // Create the directory if it doesn't exist + err = os.MkdirAll(filepath.Dir(path), 0755) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Save the file to the specified path + outFile, err := os.Create(path) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + defer outFile.Close() + + // Copy the file content + _, err = io.Copy(outFile, file) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Return success response + fmt.Fprintf(w, "File uploaded successfully\n") +} + +func downloadFileHandler(w http.ResponseWriter, r *http.Request) { + // Get the file path from the URL parameter + filePath := strings.TrimPrefix(r.URL.Path, "/download/") + if filePath == "" { + http.Error(w, "File path is required", http.StatusBadRequest) + return + } + filePath = mediaDir + filePath // prepend media directory + + // Read the file content + fileBytes, err := ioutil.ReadFile(filePath) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Set the appropriate headers + w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filePath)) + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Length", fmt.Sprintf("%d", len(fileBytes))) + + // Write the file content to the response body + _, err = w.Write(fileBytes) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } +} + +func listFilesHandler(w http.ResponseWriter, r *http.Request) { + // Get the path from the query parameter or set the default path + path := r.URL.Query().Get("path") + if path == "" { + path = mediaDir + } else { + path = mediaDir + path + } + + // List files in the specified directory + files, err := ioutil.ReadDir(path) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Build the response + var fileNames []string + for _, file := range files { + fileNames = append(fileNames, file.Name()) + } + + // Write the file list as a response + fmt.Fprintf(w, "Files in directory %s:\n", path) + for _, name := range fileNames { + fmt.Fprintf(w, "%s\n", name) + } +} + +func deleteFileHandler(w http.ResponseWriter, r *http.Request) { + // Get the file path from the URL parameter + filePath := strings.TrimPrefix(r.URL.Path, "/delete/") + if filePath == "" { + http.Error(w, "File path is required", http.StatusBadRequest) + return + } + filePath = mediaDir + filePath // prepend media directory + + // Delete the file + err := os.Remove(filePath) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // Return success response + fmt.Fprintf(w, "File deleted successfully\n") +} + + +func main() { + ips, err := LoadServersFromFile("servers.txt") + if err != nil { + fmt.Println("Error:", err) + return + } + + // Print the loaded IP addresses + fmt.Println("Loaded servers:") + for _, ip := range ips { + fmt.Println(ip) + } + + http.HandleFunc("/", getRoot) + http.HandleFunc("/hello", getHello) + http.HandleFunc("/data", getData) + http.HandleFunc("/ips", getIPs) + http.HandleFunc("/addip", addIP) + http.HandleFunc("/removeip", removeIP) + http.HandleFunc("/upload", uploadFileHandler) + http.HandleFunc("/download/", downloadFileHandler) + http.HandleFunc("/list", listFilesHandler) + http.HandleFunc("/delete/", deleteFileHandler) + + + + + + err = http.ListenAndServe(":3333", nil) + if errors.Is(err, http.ErrServerClosed) { + fmt.Printf("server closed\n") + } else if err != nil { + fmt.Printf("error starting server: %s\n", err) + os.Exit(1) + } +}