diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6ab832a4..a4d42760 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,5 +45,5 @@ jobs: file: ./Dockerfile platforms: linux/amd64,linux/arm,linux/arm64,linux/386 push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.docker_meta.outputs.tags }} - labels: ${{ steps.docker_meta.outputs.labels }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 6f72f892..d91f46b2 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,9 @@ go.work go.work.sum -# env file +# Environment variables file .env + +# Croc builds +/croc +croc_v* diff --git a/Dockerfile b/Dockerfile index f1fc0c6e..6a5fcd1f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,5 +20,9 @@ COPY --from=builder /go/croc/croc /go/croc/croc-entrypoint.sh / USER nobody +# Simple TCP health check with nc! +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD nc -z localhost 9009 || exit 1 + ENTRYPOINT ["/croc-entrypoint.sh"] CMD ["relay"] diff --git a/go.mod b/go.mod index 2905947b..b29c4b26 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/schollz/progressbar/v3 v3.18.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/stretchr/testify v1.11.1 + golang.design/x/clipboard v0.7.1 golang.org/x/crypto v0.42.0 golang.org/x/net v0.44.0 golang.org/x/sys v0.36.0 @@ -34,5 +35,8 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect github.com/twmb/murmur3 v1.1.8 // indirect + golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 // indirect + golang.org/x/image v0.28.0 // indirect + golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index ecc1c466..40178d8b 100644 --- a/go.sum +++ b/go.sum @@ -62,6 +62,8 @@ github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg= github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.design/x/clipboard v0.7.1 h1:OEG3CmcYRBNnRwpDp7+uWLiZi3hrMRJpE9JkkkYtz2c= +golang.design/x/clipboard v0.7.1/go.mod h1:i5SiIqj0wLFw9P/1D7vfILFK0KHMk7ydE72HRrUIgkg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= @@ -70,6 +72,12 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 h1:Wdx0vgH5Wgsw+lF//LJKmWOJBLWX6nprsMqnf99rYDE= +golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8= +golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE= +golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY= +golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f h1:/n+PL2HlfqeSiDCuhdBbRNlGS/g2fM4OHufalHaTVG8= +golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f/go.mod h1:ESkJ836Z6LpG6mTVAhA48LpfW/8fNR0ifStlH2axyfg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= diff --git a/main.go b/main.go index 17dbe406..f2e15dc7 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,7 @@ func main() { }() // Wait for a termination signal - _ = <-sigs + <-sigs utils.RemoveMarkedFiles() // Exit the program gracefully diff --git a/src/cli/cli.go b/src/cli/cli.go index e0aa309e..b191640c 100644 --- a/src/cli/cli.go +++ b/src/cli/cli.go @@ -119,7 +119,7 @@ func Run() (err error) { &cli.StringFlag{Name: "pass", Value: models.DEFAULT_PASSPHRASE, Usage: "password for the relay", EnvVars: []string{"CROC_PASS"}}, &cli.StringFlag{Name: "socks5", Value: "", Usage: "add a socks5 proxy", EnvVars: []string{"SOCKS5_PROXY"}}, &cli.StringFlag{Name: "connect", Value: "", Usage: "add a http proxy", EnvVars: []string{"HTTP_PROXY"}}, - &cli.StringFlag{Name: "throttleUpload", Value: "", Usage: "Throttle the upload speed e.g. 500k"}, + &cli.StringFlag{Name: "throttleUpload", Value: "", Usage: "throttle the upload speed e.g. 500k"}, } app.EnableBashCompletion = true app.HideHelp = false @@ -478,9 +478,7 @@ Or you can go back to the classic croc behavior by enabling classic mode: // save the config saveConfig(c, crocOptions) - err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders) - return } diff --git a/src/comm/comm.go b/src/comm/comm.go index b1b0f257..a0d7bbe3 100644 --- a/src/comm/comm.go +++ b/src/comm/comm.go @@ -142,7 +142,9 @@ func (c *Comm) Read() (buf []byte, numBytes int, bs []byte, err error) { log.Warnf("error setting read deadline: %v", err) } // must clear the timeout setting - defer c.connection.SetDeadline(time.Time{}) + if err := c.connection.SetDeadline(time.Time{}); err != nil { + log.Warnf("failed to clear deadline: %v", err) + } // read until we get 4 bytes for the magic header := make([]byte, 4) diff --git a/src/comm/comm_test.go b/src/comm/comm_test.go index 30925391..751b63f3 100644 --- a/src/comm/comm_test.go +++ b/src/comm/comm_test.go @@ -23,7 +23,11 @@ func TestComm(t *testing.T) { if err != nil { log.Error(err) } - defer server.Close() + defer func() { + if err := server.Close(); err != nil { + log.Error(err) + } + }() // spawn a new goroutine whenever a client connects for { connection, err := server.Accept() diff --git a/src/croc/croc.go b/src/croc/croc.go index 01019e1a..ad027c13 100644 --- a/src/croc/croc.go +++ b/src/croc/croc.go @@ -12,10 +12,8 @@ import ( "math" "net" "os" - "os/exec" "path" "path/filepath" - "runtime" "strconv" "strings" "sync" @@ -28,6 +26,7 @@ import ( "github.com/schollz/peerdiscovery" "github.com/schollz/progressbar/v3" "github.com/skip2/go-qrcode" + "golang.design/x/clipboard" "golang.org/x/term" "golang.org/x/time/rate" @@ -47,6 +46,11 @@ var ( func init() { log.SetLevel("debug") + // Initializing clipboard + err := clipboard.Init() + if err != nil { + panic(err) + } } // Debug toggles debug mode @@ -58,7 +62,7 @@ func Debug(debug bool) { } } -// Options specifies user specific options +// Options specifies user options type Options struct { IsSender bool SharedSecret string @@ -671,7 +675,8 @@ On the other computer run: (For Linux/macOS) CROC_SECRET=%[1]q croc %[2]s `, c.Options.SharedSecret, flags.String()) - copyToClipboard(c.Options.SharedSecret) + // Copying to clipboard + clipboard.Write(clipboard.FmtText, []byte(c.Options.SharedSecret)) if c.Options.ShowQrCode { showReceiveCommandQrCode(fmt.Sprintf("%[1]s", c.Options.SharedSecret)) } @@ -1828,7 +1833,6 @@ func (c *Client) updateIfRecipientHasFileInfo() (err error) { log.Debugf("hashed %s to %x using %s", fileInfo.Name, fileHash, c.Options.HashAlgorithm) log.Debugf("hashes are not equal %x != %x", fileHash, fileInfo.Hash) if errHash == nil && !c.Options.Overwrite && errRecipientFile == nil && !strings.HasPrefix(fileInfo.Name, "croc-stdin-") && !c.Options.SendingText { - missingChunks := utils.ChunkRangesToChunks(utils.MissingChunks( path.Join(fileInfo.FolderRemote, fileInfo.Name), fileInfo.Size, @@ -2134,27 +2138,3 @@ func (c *Client) sendData(i int) { } } } - -func copyToClipboard(str string) { - var cmd *exec.Cmd - switch runtime.GOOS { - case "windows": - cmd = exec.Command("clip") - case "darwin": - cmd = exec.Command("pbcopy") - case "linux": - if os.Getenv("XDG_SESSION_TYPE") == "wayland" { - cmd = exec.Command("wl-copy") - } else { - cmd = exec.Command("xclip", "-selection", "clipboard") - } - default: - return - } - cmd.Stdin = bytes.NewReader([]byte(str)) - if err := cmd.Run(); err != nil { - log.Debugf("error copying to clipboard: %v", err) - return - } - fmt.Fprintf(os.Stderr, "Code copied to clipboard\n") -} diff --git a/src/utils/utils.go b/src/utils/utils.go index 6c04b410..d4334ff0 100644 --- a/src/utils/utils.go +++ b/src/utils/utils.go @@ -281,11 +281,12 @@ func LocalIP() string { return localAddr.IP.String() } +// GenerateRandomPin returns a randomly generated pin with set lenght func GenerateRandomPin() string { s := "" max := new(big.Int) max.SetInt64(9) - for i := 0; i < NbPinNumbers; i++ { + for range NbPinNumbers { v, err := rand.Int(rand.Reader, max) if err != nil { panic(err)