package main import ( "fmt" "io" "log" "net" "net/http" "os" "path/filepath" "regexp" "strings" ) var ( validKey = regexp.MustCompile(`^[\w+\-:.\d]+$`) fileDir = "/var/lib/maz-clipsrv/files" typeDir = "/var/lib/maz-clipsrv/types" socketPath string ) type Clip struct { Name string `json:"name"` ContentType string `json:"content_type"` Data []byte `json:"-"` } func validKeyname(key string) bool { illegal := map[string]bool{"XDEBUG_SESSION_START": true, "src": true, "Packages": true} return !illegal[key] && validKey.MatchString(key) } func saveClip(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(16 << 20) if err != nil { http.Error(w, "Failed to parse form", 400) return } var saved []string for name, headers := range r.MultipartForm.File { if !validKeyname(name) { http.Error(w, "Invalid keyname", 400) return } file, err := headers[0].Open() if err != nil { http.Error(w, "File open error", 500) return } defer file.Close() data, err := io.ReadAll(file) if err != nil { http.Error(w, "Read error", 500) return } contentType := headers[0].Header.Get("Content-Type") if contentType == "" { contentType = http.DetectContentType(data) } log.Printf("Saving clip: '%s' with content type: '%s'", name, contentType) err = os.WriteFile(filepath.Join(fileDir, name), data, 0644) if err != nil { log.Printf("Error saving data: %v", err) } err = os.WriteFile(filepath.Join(typeDir, name), []byte(contentType), 0644) if err != nil { log.Printf("Error saving type: %v", err) } saved = append(saved, fmt.Sprintf("https://mazunki.cc/%s", name)) } if len(saved) == 0 { http.Error(w, "Nothing saved", 400) return } fmt.Fprintln(w, strings.Join(saved, "\n")) } func loadClip(name string) (*Clip, error) { data, err := os.ReadFile(filepath.Join(fileDir, name)) if err != nil { return nil, err } ctype, err := os.ReadFile(filepath.Join(typeDir, name)) if err != nil { ctype = []byte("text/plain; charset=utf-8") } return &Clip{ Name: name, ContentType: string(ctype), Data: data, }, nil } func serveClip(w http.ResponseWriter, r *http.Request, plain bool) { key := strings.TrimPrefix(r.URL.Path, "/") key = strings.TrimSuffix(key, "/") if key == "" { key = "src" } if !validKeyname(key) && key != "src" && key != "Packages" { http.Error(w, "Bonk!\n", 400) return } clip, err := loadClip(key) if err != nil { http.Error(w, "No such clip", 204) return } ctype := clip.ContentType if plain { ctype = "text/plain; charset=utf-8" } w.Header().Set("Content-Type", ctype) w.Write(clip.Data) log.Printf("Delivered '%s' with content type: '%s'", key, ctype) } func main() { runtimeDir := os.Getenv("XDG_RUNTIME_DIR") if runtimeDir == "" { log.Fatal("XDG_RUNTIME_DIR not set") } socketPath = filepath.Join(runtimeDir, "clipboard-mazunki-tech.sock") _ = os.Remove(socketPath) if err := os.MkdirAll(fileDir, 0755); err != nil { log.Fatalf("Failed to create fileDir: %v", err) } if err := os.MkdirAll(typeDir, 0755); err != nil { log.Fatalf("Failed to create typeDir: %v", err) } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { log.Printf("Got a new POST from %s", r.RemoteAddr) saveClip(w, r) } else if r.Method == http.MethodGet { log.Printf("Got a new GET from %s", r.RemoteAddr) serveClip(w, r, false) } }) http.HandleFunc("/raw/", func(w http.ResponseWriter, r *http.Request) { serveClip(w, r, true) }) log.Printf("Listening on UNIX socket: %s", socketPath) listener, err := net.Listen("unix", socketPath) if err != nil { log.Fatalf("Failed to bind to socket: %v", err) } if err := os.Chmod(socketPath, 0666); err != nil { log.Fatalf("Failed to chmod socket: %v", err) } log.Fatal(http.Serve(listener, nil)) }