diff --git a/cmd/cli/getClipboard.go b/cmd/cli/getClipboard.go deleted file mode 100644 index fd990cf..0000000 --- a/cmd/cli/getClipboard.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "os" - - "github.com/AYM1607/ccclip/internal/configfile" - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(getClipboardCmd) -} - -var getClipboardCmd = &cobra.Command{ - Use: "get-clipboard", - Short: "get the currently stored clipboard", - RunE: func(cmd *cobra.Command, args []string) error { - cc, err := configfile.EnsureAndGet() - if err != nil { - return err - } - - if cc.DeviceId == "" { - return errors.New("you must log in and register your device") - } - pvk, err := configfile.LoadPrivateKey() - if err != nil { - return fmt.Errorf("could not load this device's private key: %w", err) - } - - plain, err := apiclient.GetClipboard(cc.DeviceId, pvk) - if err != nil { - return fmt.Errorf("could not set clipboard: %w", err) - } - - fmt.Printf("Your current clipbard is:") - fmt.Fprintf(os.Stdout, plain) - return nil - }, -} diff --git a/cmd/cli/getDevices.go b/cmd/cli/getDevices.go deleted file mode 100644 index e122093..0000000 --- a/cmd/cli/getDevices.go +++ /dev/null @@ -1,34 +0,0 @@ -package main - -import ( - "github.com/spf13/cobra" -) - -func init() { - rootCmd.AddCommand(getDevicesCmd) -} - -var getDevicesCmd = &cobra.Command{ - Use: "get-devices", - Short: "Register a user with a given email and password", - RunE: func(cmd *cobra.Command, args []string) error { - // cc, err := configfile.EnsureAndGet() - // if err != nil { - // return err - // } - // if cc.DeviceId == "" { - // return errors.New("your device is not registered") - // } - // pvk, err := configfile.LoadPrivateKey() - // if err != nil { - // return err - // } - // devices, err := apiclient.GetDevices(cc.DeviceId, pvk) - // if err != nil { - // return err - // } - - // return json.NewEncoder(os.Stdout).Encode(devices) - return nil - }, -} diff --git a/cmd/cli/root.go b/cmd/cli/root.go index 8d0cbbc..b2ccf38 100644 --- a/cmd/cli/root.go +++ b/cmd/cli/root.go @@ -1,23 +1,84 @@ package main import ( + "errors" "fmt" + "io" "log" "os" "path" "github.com/AYM1607/ccclip/internal/configfile" + + "github.com/mattn/go-isatty" "github.com/spf13/cobra" ) +func getClipboard() (string, error) { + cc, err := configfile.EnsureAndGet() + if err != nil { + return "", err + } + + if cc.DeviceId == "" { + return "", errors.New("you must log in and register your device") + } + pvk, err := configfile.LoadPrivateKey() + if err != nil { + return "", fmt.Errorf("could not load this device's private key: %w", err) + } + + plain, err := apiclient.GetClipboard(cc.DeviceId, pvk) + if err != nil { + return "", fmt.Errorf("could not set clipboard: %w", err) + } + + return plain, nil +} + +func setClipboard(clip []byte) error { + cc, err := configfile.EnsureAndGet() + if err != nil { + return err + } + + if cc.DeviceId == "" { + return errors.New("you must log in and register your device") + } + pvk, err := configfile.LoadPrivateKey() + if err != nil { + return fmt.Errorf("could not load this device's private key: %w", err) + } + + err = apiclient.SetClipboard(clip, cc.DeviceId, pvk) + if err != nil { + return fmt.Errorf("could not set clipboard: %w", err) + } + return nil +} + // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "ccclip", Short: "copy strings to and from your end to end encrypted cloud clipboard", Long: `copy strings to and from your end to end encrypted cloud clipboard`, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, + RunE: func(cmd *cobra.Command, args []string) error { + if isatty.IsTerminal(os.Stdin.Fd()) || isatty.IsCygwinTerminal(os.Stdin.Fd()) { + // Nothing piped through stdin. Reading clipboard. + clip, err := getClipboard() + if err != nil { + return err + } + _, err = os.Stdout.Write([]byte(clip)) + return err + } + + clip, err := io.ReadAll(os.Stdin) + if err != nil { + return err + } + return setClipboard(clip) + }, } func init() { diff --git a/cmd/cli/setClipboard.go b/cmd/cli/setClipboard.go deleted file mode 100644 index b329fd4..0000000 --- a/cmd/cli/setClipboard.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "errors" - "fmt" - - "github.com/AYM1607/ccclip/internal/configfile" - "github.com/spf13/cobra" -) - -var clipboard string - -func init() { - rootCmd.AddCommand(setClipboardCmd) - - setClipboardCmd.Flags().StringVar(&clipboard, "clip", "", "the string to send") - setClipboardCmd.MarkFlagRequired("clip") -} - -var setClipboardCmd = &cobra.Command{ - Use: "set-clipboard", - Short: "set the given string as the cloud clipboard", - RunE: func(cmd *cobra.Command, args []string) error { - cc, err := configfile.EnsureAndGet() - if err != nil { - return err - } - - if cc.DeviceId == "" { - return errors.New("you must log in and register your device") - } - pvk, err := configfile.LoadPrivateKey() - if err != nil { - return fmt.Errorf("could not load this device's private key: %w", err) - } - - err = apiclient.SetClipboard(clipboard, cc.DeviceId, pvk) - if err != nil { - return fmt.Errorf("could not set clipboard: %w", err) - } - return nil - }, -} diff --git a/go.mod b/go.mod index 8cf5f16..9ea2886 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/gorilla/mux v1.8.0 + github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-sqlite3 v1.14.18 github.com/oklog/ulid/v2 v2.1.0 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index 64876d1..7eeb01f 100644 --- a/go.sum +++ b/go.sum @@ -3,6 +3,8 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI= github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= @@ -15,6 +17,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= diff --git a/internal/server/client/client.go b/internal/server/client/client.go index aacdd95..a53761e 100644 --- a/internal/server/client/client.go +++ b/internal/server/client/client.go @@ -78,7 +78,7 @@ func (c *Client) RegisterDevice(email, password string, devicePublicKey []byte) return &res, nil } -func (c *Client) SetClipboard(plaintext string, deviceId string, pvk *ecdh.PrivateKey) error { +func (c *Client) SetClipboard(plaintext []byte, deviceId string, pvk *ecdh.PrivateKey) error { devices, err := c.getDevices(deviceId, pvk) if err != nil { return err diff --git a/internal/server/client/encryption.go b/internal/server/client/encryption.go index 4418c22..fa46b77 100644 --- a/internal/server/client/encryption.go +++ b/internal/server/client/encryption.go @@ -7,11 +7,11 @@ import ( "github.com/AYM1607/ccclip/pkg/crypto" ) -func encryptForAll(plaintext string, pvk *ecdh.PrivateKey, devices []*api.Device) map[string][]byte { +func encryptForAll(plaintext []byte, pvk *ecdh.PrivateKey, devices []*api.Device) map[string][]byte { res := map[string][]byte{} for _, d := range devices { key := crypto.NewSharedKey(pvk, crypto.PublicKeyFromBytes(d.PublicKey), crypto.SendDirection) - res[d.ID] = crypto.Encrypt(key, []byte(plaintext)) + res[d.ID] = crypto.Encrypt(key, plaintext) } return res }