mirror of
https://github.com/schollz/croc.git
synced 2025-10-11 05:11:06 +02:00
feat: a better clipboard, a simple TCP healthcheck and fixed docker deployments
This commit is contained in:
parent
83aef2eac5
commit
4499f841bb
11 changed files with 44 additions and 39 deletions
4
.github/workflows/deploy.yml
vendored
4
.github/workflows/deploy.yml
vendored
|
@ -45,5 +45,5 @@ jobs:
|
||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
platforms: linux/amd64,linux/arm,linux/arm64,linux/386
|
platforms: linux/amd64,linux/arm,linux/arm64,linux/386
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -21,5 +21,9 @@
|
||||||
go.work
|
go.work
|
||||||
go.work.sum
|
go.work.sum
|
||||||
|
|
||||||
# env file
|
# Environment variables file
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
# Croc builds
|
||||||
|
/croc
|
||||||
|
croc_v*
|
||||||
|
|
|
@ -20,5 +20,9 @@ COPY --from=builder /go/croc/croc /go/croc/croc-entrypoint.sh /
|
||||||
|
|
||||||
USER nobody
|
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"]
|
ENTRYPOINT ["/croc-entrypoint.sh"]
|
||||||
CMD ["relay"]
|
CMD ["relay"]
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -17,6 +17,7 @@ require (
|
||||||
github.com/schollz/progressbar/v3 v3.18.0
|
github.com/schollz/progressbar/v3 v3.18.0
|
||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
|
golang.design/x/clipboard v0.7.1
|
||||||
golang.org/x/crypto v0.42.0
|
golang.org/x/crypto v0.42.0
|
||||||
golang.org/x/net v0.44.0
|
golang.org/x/net v0.44.0
|
||||||
golang.org/x/sys v0.36.0
|
golang.org/x/sys v0.36.0
|
||||||
|
@ -34,5 +35,8 @@ require (
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
|
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
|
||||||
github.com/twmb/murmur3 v1.1.8 // 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
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
8
go.sum
8
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 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
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=
|
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-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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
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.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
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/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.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.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
|
2
main.go
2
main.go
|
@ -47,7 +47,7 @@ func main() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Wait for a termination signal
|
// Wait for a termination signal
|
||||||
_ = <-sigs
|
<-sigs
|
||||||
utils.RemoveMarkedFiles()
|
utils.RemoveMarkedFiles()
|
||||||
|
|
||||||
// Exit the program gracefully
|
// Exit the program gracefully
|
||||||
|
|
|
@ -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: "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: "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: "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.EnableBashCompletion = true
|
||||||
app.HideHelp = false
|
app.HideHelp = false
|
||||||
|
@ -478,9 +478,7 @@ Or you can go back to the classic croc behavior by enabling classic mode:
|
||||||
|
|
||||||
// save the config
|
// save the config
|
||||||
saveConfig(c, crocOptions)
|
saveConfig(c, crocOptions)
|
||||||
|
|
||||||
err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders)
|
err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,9 @@ func (c *Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
|
||||||
log.Warnf("error setting read deadline: %v", err)
|
log.Warnf("error setting read deadline: %v", err)
|
||||||
}
|
}
|
||||||
// must clear the timeout setting
|
// 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
|
// read until we get 4 bytes for the magic
|
||||||
header := make([]byte, 4)
|
header := make([]byte, 4)
|
||||||
|
|
|
@ -23,7 +23,11 @@ func TestComm(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error(err)
|
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
|
// spawn a new goroutine whenever a client connects
|
||||||
for {
|
for {
|
||||||
connection, err := server.Accept()
|
connection, err := server.Accept()
|
||||||
|
|
|
@ -12,10 +12,8 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -28,6 +26,7 @@ import (
|
||||||
"github.com/schollz/peerdiscovery"
|
"github.com/schollz/peerdiscovery"
|
||||||
"github.com/schollz/progressbar/v3"
|
"github.com/schollz/progressbar/v3"
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
|
"golang.design/x/clipboard"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
|
@ -47,6 +46,11 @@ var (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetLevel("debug")
|
log.SetLevel("debug")
|
||||||
|
// Initializing clipboard
|
||||||
|
err := clipboard.Init()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug toggles debug mode
|
// Debug toggles debug mode
|
||||||
|
@ -58,7 +62,7 @@ func Debug(debug bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options specifies user specific options
|
// Options specifies user options
|
||||||
type Options struct {
|
type Options struct {
|
||||||
IsSender bool
|
IsSender bool
|
||||||
SharedSecret string
|
SharedSecret string
|
||||||
|
@ -671,7 +675,8 @@ On the other computer run:
|
||||||
(For Linux/macOS)
|
(For Linux/macOS)
|
||||||
CROC_SECRET=%[1]q croc %[2]s
|
CROC_SECRET=%[1]q croc %[2]s
|
||||||
`, c.Options.SharedSecret, flags.String())
|
`, c.Options.SharedSecret, flags.String())
|
||||||
copyToClipboard(c.Options.SharedSecret)
|
// Copying to clipboard
|
||||||
|
clipboard.Write(clipboard.FmtText, []byte(c.Options.SharedSecret))
|
||||||
if c.Options.ShowQrCode {
|
if c.Options.ShowQrCode {
|
||||||
showReceiveCommandQrCode(fmt.Sprintf("%[1]s", c.Options.SharedSecret))
|
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("hashed %s to %x using %s", fileInfo.Name, fileHash, c.Options.HashAlgorithm)
|
||||||
log.Debugf("hashes are not equal %x != %x", fileHash, fileInfo.Hash)
|
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 {
|
if errHash == nil && !c.Options.Overwrite && errRecipientFile == nil && !strings.HasPrefix(fileInfo.Name, "croc-stdin-") && !c.Options.SendingText {
|
||||||
|
|
||||||
missingChunks := utils.ChunkRangesToChunks(utils.MissingChunks(
|
missingChunks := utils.ChunkRangesToChunks(utils.MissingChunks(
|
||||||
path.Join(fileInfo.FolderRemote, fileInfo.Name),
|
path.Join(fileInfo.FolderRemote, fileInfo.Name),
|
||||||
fileInfo.Size,
|
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")
|
|
||||||
}
|
|
||||||
|
|
|
@ -281,11 +281,12 @@ func LocalIP() string {
|
||||||
return localAddr.IP.String()
|
return localAddr.IP.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateRandomPin returns a randomly generated pin with set lenght
|
||||||
func GenerateRandomPin() string {
|
func GenerateRandomPin() string {
|
||||||
s := ""
|
s := ""
|
||||||
max := new(big.Int)
|
max := new(big.Int)
|
||||||
max.SetInt64(9)
|
max.SetInt64(9)
|
||||||
for i := 0; i < NbPinNumbers; i++ {
|
for range NbPinNumbers {
|
||||||
v, err := rand.Int(rand.Reader, max)
|
v, err := rand.Int(rand.Reader, max)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue