package grpcaddr import ( "fmt" "os" "path/filepath" "runtime" "strconv" "strings" ) const socketName = "keepassgo-grpc.sock" func Default(goos string) string { if strings.EqualFold(strings.TrimSpace(goos), "android") { return "off" } if strings.EqualFold(strings.TrimSpace(goos), "windows") { return "127.0.0.1:47777" } return "unix://" + DefaultSocketPath() } func DefaultSocketPath() string { return filepath.Join(runtimeDir(), "keepassgo", socketName) } func runtimeDir() string { if dir := strings.TrimSpace(os.Getenv("XDG_RUNTIME_DIR")); dir != "" { return dir } if runtime.GOOS != "windows" { uid := strconv.Itoa(os.Getuid()) runUserDir := filepath.Join("/run/user", uid) if info, err := os.Stat(runUserDir); err == nil && info.IsDir() { return runUserDir } } return filepath.Join(os.TempDir(), fmt.Sprintf("keepassgo-runtime-%d", os.Getuid())) } func Parse(raw string) (network, endpoint string, err error) { value := strings.TrimSpace(raw) switch { case value == "": return "", "", fmt.Errorf("gRPC address is required") case strings.EqualFold(value, "off"): return "", "", nil case strings.HasPrefix(value, "unix://"): path := strings.TrimSpace(strings.TrimPrefix(value, "unix://")) if path == "" { return "", "", fmt.Errorf("unix gRPC socket path is required") } return "unix", path, nil case strings.HasPrefix(value, "tcp://"): addr := strings.TrimSpace(strings.TrimPrefix(value, "tcp://")) if addr == "" { return "", "", fmt.Errorf("tcp gRPC address is required") } return "tcp", addr, nil case strings.HasPrefix(value, "/"): return "unix", value, nil default: return "tcp", value, nil } }