// Copyright (c) 2026 Storm Dragon // Authors: Storm Dragon, Angus Kola // SPDX-License-Identifier: GPL-3.0-or-later package clipboard import ( "encoding/json" "io" "net/url" "os" "path" "path/filepath" "strconv" "strings" "syscall" ) // Snapshot contains only the clipboard facts needed for Cthulhu's announcement. type Snapshot struct { Text string `json:"text"` HasText bool `json:"hasText"` Image bool `json:"image"` URIs []string `json:"uris"` } // WriteMessage is called only by the short lived clipboard helper process. // URI filesystem checks stay here so the parent can enforce a read deadline. func WriteMessage(output io.Writer) error { snapshot, err := read_native() if err != nil { return err } return json.NewEncoder(output).Encode(struct { Message string `json:"message"` }{Message: Format(snapshot)}) } func Format(snapshot Snapshot) string { if snapshot.Image { return "The clipboard contains a image" } if len(snapshot.URIs) != 0 { return format_uris(snapshot.URIs) } if snapshot.HasText { return "Text in clipboard " + snapshot.Text } return "The clipboard is empty" } func format_uris(uris []string) string { objects := make([]string, 0, len(uris)) for _, raw := range uris { if raw == "" { continue } parsed, err := url.Parse(raw) if err != nil { objects = append(objects, raw) continue } name := path.Base(parsed.Path) if name == "." || name == "/" { name = raw } parts := []string{name} if parsed.Scheme == "file" && (parsed.Host == "" || parsed.Host == "localhost") { localPath := parsed.Path link := false if info, err := os.Lstat(localPath); err == nil && info.Mode()&os.ModeSymlink != 0 { link = true } if info, err := os.Stat(localPath); err == nil { if info.IsDir() { parts = append(parts, "Folder") } else if info.Mode().IsRegular() { parts = append(parts, "File") } if !link && is_mount(localPath, info) { parts = append(parts, "Disk") } } if link { parts = append(parts, "Link") } } objects = append(objects, strings.Join(parts, " ")) } if len(objects) == 0 { return "The clipboard is empty" } label := " Object in clipboard " if len(objects) > 1 { label = " Objects in clipboard " } return strconv.Itoa(len(objects)) + label + strings.Join(objects, " ") } func is_mount(localPath string, info os.FileInfo) bool { parentPath := filepath.Dir(filepath.Clean(localPath)) parent, err := os.Stat(parentPath) if err != nil { return false } currentStat, currentOK := info.Sys().(*syscall.Stat_t) parentStat, parentOK := parent.Sys().(*syscall.Stat_t) return currentOK && parentOK && (currentStat.Dev != parentStat.Dev || currentStat.Ino == parentStat.Ino) }