Compare commits

..

106 Commits

Author SHA1 Message Date
Zack Scholl f6012939f3 v10.1.1 2024-11-28 03:02:27 -08:00
Zack Scholl bda3dcc670 Remove stun Fixes #849 2024-11-28 03:01:12 -08:00
Zack a96e7945e1
Merge pull request #847 from Ozoniuss/finish-qr-code
Add a qrcode flag
2024-11-24 03:41:38 -08:00
Ozoniuss 278e1b4099
Add a qrcode flag
- Introduces a new flag which allows displaying the receive command
  using a qr code.
- Adds a newline after the message indicating that the code was copied
  to the clipboard.
2024-11-24 13:33:38 +02:00
Zack c369c78b42
Merge pull request #843 from matthewfeickert/docs/add-conda-forge
docs: Add conda-forge install instructions for pixi and conda
2024-11-13 11:20:34 -08:00
Matthew Feickert a61a461436
docs: Add conda-forge install instructions for pixi and conda
* The conda-forge build supports Linux, macOS, and Windows.
   - c.f. https://github.com/conda-forge/croc-feedstock/
2024-11-13 12:17:51 -07:00
Zack d616b8fff7
Merge pull request #837 from gamagoat/mask-pass
Mask password in logs
2024-11-12 18:25:49 -08:00
gamagoat 3252f2abb2 Mask password in logs 2024-11-13 10:03:23 +09:00
Zack Scholl 53323cb8c4 v10.1.0 2024-11-08 15:29:45 -08:00
Zack Scholl d7ebb3d97c update dependencies 2024-11-08 15:28:48 -08:00
Zack 30684fb383
Merge pull request #825 from davidwoood/main
chore: fix some function names in comment
2024-10-21 01:23:03 -07:00
David Wood 09376c5c4b
chore: fix some function names in comment 2024-10-21 14:58:54 +08:00
Zack 917d9f16b4
Merge pull request #824 from bitraid/improve-clipboard-copy
Improve clipboard copy
2024-10-12 06:28:44 -07:00
bitraid 1adf845284
clipboard copy: add Linux/Wayland support 2024-10-12 14:53:48 +03:00
bitraid 10bd3b47e9
clipboard copy: don't run clip through cmd on Windows 2024-10-12 13:51:24 +03:00
Zack 0d48e346ad
Merge pull request #822 from elliot40404/feature/copy-to-clipboard
Added copy to clipboard functionality for windows,linux and mac
2024-10-07 15:30:15 -07:00
Elliot 234eb86f69
fixed log statement formatting error 2024-10-08 02:02:58 +05:30
Elliot 856e1c966e
Added copy to clipboard functionality for windows,linux and mac 2024-10-07 03:59:48 +05:30
Zack Scholl 12cc09f6e5 chore: update dependencies 2024-10-06 06:46:14 -07:00
Zack 7470ed1ea2 replace gortc.io Fixes #821 2024-10-05 15:49:25 -07:00
Zack 555cfc085a
Merge pull request #818 from schollz:schollz/issue817
add option -multicast to change multicast address
2024-10-03 20:06:46 -07:00
Zack Scholl 325cff6661 add option -multicast to change multicast address
Fixes #817
2024-10-03 20:06:32 -07:00
Zack Scholl 71369dee36 upgrade deps 2024-10-03 20:01:53 -07:00
Zack Scholl 146f6413a9 fix release.yml 2024-10-01 07:27:45 -07:00
Zack Scholl 38acf6f7e3 update deps 2024-10-01 07:25:09 -07:00
Zack Scholl 81d3593164 v10.0.13 2024-10-01 07:24:36 -07:00
Zack Scholl 3ca13a405f update builds 2024-10-01 06:56:15 -07:00
Zack Scholl b0a01a6634 fix ci 2024-10-01 06:50:07 -07:00
Zack Scholl c1392acb70 minimum go version 1.22 2024-10-01 06:37:55 -07:00
Zack Scholl 73ca44f064 inline dependencies 2024-10-01 06:36:57 -07:00
Zack Scholl a7235e1fcd fix ci 2024-10-01 06:10:08 -07:00
Zack Scholl 7bb1ea7a01 fix ci 2024-10-01 06:06:36 -07:00
Zack Scholl 4266ff0e41 fix ci 2024-10-01 06:02:10 -07:00
Zack Scholl 2d9769837f go mod tidy 2024-10-01 05:56:11 -07:00
Zack Scholl c275151ae4 add builds to CI 2024-10-01 05:55:09 -07:00
Zack 9231dc6bdd
Merge pull request #814 from schollz/dependabot/go_modules/github.com/schollz/progressbar/v3-3.16.0
build(deps): bump github.com/schollz/progressbar/v3 from 3.14.6 to 3.16.0
2024-10-01 05:50:44 -07:00
dependabot[bot] 2e18768770
build(deps): bump github.com/schollz/progressbar/v3
Bumps [github.com/schollz/progressbar/v3](https://github.com/schollz/progressbar) from 3.14.6 to 3.16.0.
- [Release notes](https://github.com/schollz/progressbar/releases)
- [Commits](https://github.com/schollz/progressbar/compare/v3.14.6...v3.16.0)

---
updated-dependencies:
- dependency-name: github.com/schollz/progressbar/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-24 08:46:08 +00:00
Zack Scholl 5c5e00310a benchmark new 2024-09-23 05:25:38 -07:00
Zack 9be175f1b0
Merge pull request #811 from schollz:schollz/issue796
fix: check whether path separator + ..
2024-09-17 06:39:31 -07:00
Zack Scholl 8c4594ad31 fix: check whether path separator + .. 2024-09-17 06:39:04 -07:00
Zack Scholl 519ce8c669 chore: update dependencies 2024-09-06 08:34:46 -07:00
Zack 76b1df5096 rm logging from main.go 2024-09-05 08:00:33 -07:00
Zack Scholl d6f1a63b7b update dependencies 2024-09-05 06:48:43 -07:00
Zack d0da7aafa2
Merge pull request #803 from schollz/dependabot/go_modules/golang.org/x/sys-0.25.0
build(deps): bump golang.org/x/sys from 0.24.0 to 0.25.0
2024-09-05 06:43:22 -07:00
dependabot[bot] ca8c36f38b
build(deps): bump golang.org/x/sys from 0.24.0 to 0.25.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.24.0 to 0.25.0.
- [Commits](https://github.com/golang/sys/compare/v0.24.0...v0.25.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-05 08:05:41 +00:00
Zack f9241b73fd
Merge pull request #801 from schollz:schollz/issue799
Schollz/issue799
2024-09-03 18:28:53 +02:00
Zack bb74eafd36 Remove Temporary Files if the program terminates abnormal.
Fixes #799
2024-09-03 09:28:42 -07:00
Zack 149d7364fb simplify cleanup 2024-09-03 09:16:07 -07:00
Zack cdf3aa0a31
Merge pull request #800 from Prince-Bhagat/adding-temp-directory-for-managing-temporary-files
Remove Temporary Files if the program terminates abnormal
2024-09-03 18:10:37 +02:00
Prince e663aa90cb updated log message 2024-09-03 19:49:56 -07:00
Prince 986d005449 removed unnessary file 2024-09-03 19:43:28 -07:00
Prince 0d8e4e10d6 added cleanup function to remove temporary file 2024-09-03 18:56:46 -07:00
Prince 95de3790d7 added signal for programme termination 2024-09-03 18:27:19 -07:00
Zack Scholl defee4b4f6 disable diskusage 2024-09-01 15:24:10 -07:00
Zack Scholl c146b150b8 fix mismatch 2024-09-01 14:47:40 -07:00
Zack a29b8e6d1d 10.0.11 -> 10.0.12 2024-09-01 14:38:55 -07:00
Zack 4c1facd68e chore: update deps 2024-09-01 14:37:33 -07:00
Zack 0f1d75a2ef refactor formatter 2024-09-01 14:35:36 -07:00
Zack 0017def27c
Merge pull request #794 from asukaminato0721/term.GetSize
use term.GetSize
2024-09-01 23:27:34 +02:00
Asuka Minato 319a403082 fix long file name 2024-09-01 21:39:40 +09:00
Asuka Minato 90ed1f797e add error handling 2024-08-31 00:23:21 +09:00
Asuka Minato bc9dbfd905 use term.GetSize 2024-08-31 00:08:25 +09:00
Zack 01609df902
Merge pull request #789 from schollz/dependabot/go_modules/github.com/kalafut/imohash-1.1.0
build(deps): bump github.com/kalafut/imohash from 1.0.4 to 1.1.0
2024-08-30 07:23:56 +02:00
Zack 6fbb02c196
Merge pull request #792 from schollz/schollz/issue791
feature: gracefully exit when not enough disk space
2024-08-30 07:17:30 +02:00
Zack Scholl 1b81055552 feature: gracefully exit when not enough disk space
Fixes #791
2024-08-29 22:16:12 -07:00
dependabot[bot] de623679fb
build(deps): bump github.com/kalafut/imohash from 1.0.4 to 1.1.0
Bumps [github.com/kalafut/imohash](https://github.com/kalafut/imohash) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/kalafut/imohash/releases)
- [Changelog](https://github.com/kalafut/imohash/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kalafut/imohash/compare/v1.0.4...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/kalafut/imohash
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-28 08:56:51 +00:00
Zack Scholl f8cf2eeb82 Revert "update to imohash v1.1.0 (Fixes #786)"
This reverts commit 565f252628.
2024-08-27 23:22:00 -07:00
Zack Scholl 565f252628 update to imohash v1.1.0 (Fixes #786) 2024-08-27 21:44:39 -07:00
Zack d49aaa05fe
Merge pull request #785 from nhtzr/feature/message
Show recommended croc commands for both Windows and Linux/OSX
2024-08-16 20:47:04 -07:00
vi'01-1'et df5b2994f6 Update cli.go to use inline environment variables instead of export
Also removed unnecessary quotes
2024-08-16 21:36:49 -06:00
Ezequiel Rosas 1a43826308 Make receive instructions copypaste-able 2024-08-13 12:50:48 -06:00
Zack 69af916d36 chore: update dependencies 2024-08-07 19:28:05 -07:00
Zack Scholl bf26db019c v10.0.11 2024-07-30 10:07:37 -07:00
Zack Scholl 35bf1548c4 chore: update dependencies 2024-07-30 10:07:02 -07:00
Zack Scholl f7bad72f6a chore: debug mode prints more information 2024-07-30 10:06:01 -07:00
Zack Scholl f32d060bef support for armv8l Fixes #769 2024-07-30 09:47:54 -07:00
Zack 6f3e0f1eaf
Merge pull request #767 from tnothy/fix-throttling-upload-speed-limit
fix upload speed throttling
2024-07-29 12:58:56 -07:00
tnothy 8681a4dc6d fix upload speed throttling 2024-07-29 21:46:25 +02:00
Zack 07c0a804d7 chore: update dependencies 2024-07-29 12:22:11 -07:00
Zack 5b93408c6e chore: update deps, change multicast address 2024-07-29 12:20:22 -07:00
Zack dccd6fe395
Merge pull request #766 from tnothy/fix-restore-ignored-test
fix test case name
2024-07-29 06:19:25 -07:00
tnothy 5a6f36626d fix test case name 2024-07-28 21:23:56 +02:00
Zack Scholl 677f44da6d check if busybox 2024-07-28 08:35:19 -07:00
Zack 66efe74094
Merge pull request #762 from doc75/fix_install_warning
prevent error message before insstalling completion file for non root user
2024-07-28 08:19:51 -07:00
Zack 5da253e940
Merge pull request #763 from tnothy/ports-and-transfers
define relay ports by amount
2024-07-28 08:18:51 -07:00
Zack Scholl e439b65daa fix tests 2024-07-28 08:18:21 -07:00
tnothy 6413c1c3e1 define relay ports by amount 2024-07-28 09:56:43 +02:00
Zack Scholl ce3c65ef1d chore: spelling 2024-07-27 10:44:30 -07:00
Guillaume Virlet 42bb64c434 prevent error message before insstalling completion file for non root user 2024-07-27 10:14:14 +02:00
Zack 8f226f72b6 print bytes 2024-07-25 08:41:48 -07:00
Zack 4f1a6a8d4f prevent more filenames 2024-07-25 08:36:56 -07:00
Zack 9235c341f9
Merge pull request #761 from schollz/schollz/issue756 2024-07-25 08:26:09 -07:00
Zack b2f446fd6b croc --classic Yes/no prompt default is backwards
Fixes #756
2024-07-25 08:25:54 -07:00
Zack 5ea4661e4b fix name 2024-07-20 10:22:53 -07:00
Zack 522ef9ef23 word change 2024-07-09 06:25:53 -07:00
Zack bc8b4b8ef9 update readme 2024-07-09 06:22:25 -07:00
clemisch d7c7440ae4
Add receiving on Linux and classic mode to README (#753) 2024-07-09 06:09:56 -07:00
Zack Scholl 527af8a612 redo issue terminology 2024-07-07 17:55:00 -07:00
Alex Bledea da51eb8da3
Refactor tcp (#749)
* Refactor TCP server initialization

This refactor uses the functional options pattern to extract away the
optional TCP server configuration parameters. This:

- improves overall readability, by moving away from global variables
- makes it easier to configure the tcp server for tests

* Use ticker instead of for loop for room deletion

Go offers a ticker abstraction designed for performing tasks at
a regular interval, and this change uses the ticker for tcp room
deletion. It also cleans up the deletion goroutine gracefully.

* Add local relay interaction diagram

The diagram sketches out the interaction between clients and a local
relay.

* Add debug logs for room cleanup

These would be useful for future development (e.g.
adding a stopping mechanism for the TCP listener).
2024-07-07 17:49:29 -07:00
Zack b5da962bd1 chore: update dependencies 2024-07-07 15:21:57 -07:00
Zack 72e51d8c2a v10.0.10 2024-07-07 15:21:35 -07:00
Zack c9bc41fc58 create armv5 build
Fixes #752
2024-07-07 15:20:22 -07:00
Zack 94cc704928
Merge pull request #751 from schollz/dependabot/go_modules/github.com/minio/highwayhash-1.0.3
build(deps): bump github.com/minio/highwayhash from 1.0.2 to 1.0.3
2024-07-07 13:42:42 -07:00
dependabot[bot] 6b25ca4bff
build(deps): bump github.com/minio/highwayhash from 1.0.2 to 1.0.3
Bumps [github.com/minio/highwayhash](https://github.com/minio/highwayhash) from 1.0.2 to 1.0.3.
- [Release notes](https://github.com/minio/highwayhash/releases)
- [Commits](https://github.com/minio/highwayhash/compare/v1.0.2...v1.0.3)

---
updated-dependencies:
- dependency-name: github.com/minio/highwayhash
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-05 08:57:37 +00:00
Zack 8577745d74
Merge pull request #750 from schollz:schollz/issue574
Sending folders from the root of a drive always goes to the same path on the receiver's end
2024-07-04 05:52:38 -07:00
Zack Scholl 232e162f8c Sending folders from the root of a drive always goes to the same path on the receiver's end
Fixes #574
2024-07-04 05:52:09 -07:00
25 changed files with 1161 additions and 273 deletions

View File

@ -1,31 +1,9 @@
---
name: Bug report
about: Create a report to help us improve
name: New issue
about: Create an issue
title: ''
assignees: ''
---
<!-- The comments between these brackets won't show up in the submitted issue (as you can see in the Preview). -->
<!-- Please try to download latest, https://github.com/schollz/croc/releases/latest of croc before reporting a bug! -->
## Describe the bug
## To Reproduce
Steps to reproduce the behavior:
1.
2.
3.
4.
## Expected behaviour
## Version
## Additional context
*Read this and delete before submitting:* Thanks for starting a discussion! Please provide as much context as possible so that others can understand your thoughts. If you have a specific change in mind, consider submitting a pull request instead.

View File

@ -1,20 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -13,6 +13,40 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.20'
go-version: '1.23'
- run: go version
- run: go test -v ./...
- name: Build files
run: |
go version
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -ldflags '-extldflags "-static"' -o croc.exe
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc
GOARM=5 CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags '-extldflags "-static"' -o croc
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags '-s -extldflags "-sectcreate __TEXT __info_plist Info.plist"' -o croc
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags '-s -extldflags "-sectcreate __TEXT __info_plist Info.plist"' -o croc
CGO_ENABLED=0 GOOS=dragonfly GOARCH=amd64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=netbsd GOARCH=386 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=netbsd GOARCH=amd64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=netbsd GOARCH=arm64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 go build -ldflags '' -o croc
CGO_ENABLED=0 GOOS=openbsd GOARCH=arm64 go build -ldflags '' -o croc
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20.7' # go1.20.8+ refuses to build go1.22 code...
- name: Build Windows 7
run: |
go version
rm go.mod go.sum
go mod init github.com/schollz/croc/v10
go mod tidy
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe

View File

@ -17,17 +17,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.20'
- name: Build Windows 7
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-64bit.zip croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-32bit.zip croc.exe
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
go-version: '1.23'
- name: Prepare source tarball
run: |
git clone -b ${{ github.event.release.name }} --depth 1 https://github.com/schollz/croc croc-${{ github.event.release.name }}
@ -49,6 +39,8 @@ jobs:
tar -czvf croc_${{ github.event.release.name }}_Linux-32bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc
tar -czvf croc_${{ github.event.release.name }}_Linux-ARM.tar.gz croc LICENSE
GOARM=5 CGO_ENABLED=0 GOOS=linux GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc
tar -czvf croc_${{ github.event.release.name }}_Linux-ARMv5.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags '-extldflags "-static"' -o croc
tar -czvf croc_${{ github.event.release.name }}_Linux-ARM64.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -ldflags '-s -extldflags "-sectcreate __TEXT __info_plist Info.plist"' -o croc
@ -71,6 +63,20 @@ jobs:
tar -czvf croc_${{ github.event.release.name }}_OpenBSD-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=openbsd GOARCH=arm64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_OpenBSD-ARM64.tar.gz croc LICENSE
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20.7' # go1.20.8+ refuses to build go1.22 code...
- name: Build Windows 7
run: |
go version
rm go.mod go.sum
go mod init github.com/schollz/croc/v10
go mod tidy
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-64bit.zip croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-32bit.zip croc.exe
- name: Create checksums.txt
run: |
touch croc_${{ github.event.release.name }}_checksums.txt
@ -84,6 +90,7 @@ jobs:
sha256sum croc_${{ github.event.release.name }}_Linux-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Linux-32bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Linux-ARM.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Linux-ARMv5.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Linux-ARM64.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_macOS-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_macOS-ARM64.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
@ -110,6 +117,7 @@ jobs:
croc_${{ github.event.release.name }}_Linux-64bit.tar.gz
croc_${{ github.event.release.name }}_Linux-32bit.tar.gz
croc_${{ github.event.release.name }}_Linux-ARM.tar.gz
croc_${{ github.event.release.name }}_Linux-ARMv5.tar.gz
croc_${{ github.event.release.name }}_Linux-ARM64.tar.gz
croc_${{ github.event.release.name }}_macOS-64bit.tar.gz
croc_${{ github.event.release.name }}_macOS-ARM64.tar.gz

View File

@ -4,7 +4,7 @@
src="https://user-images.githubusercontent.com/6550035/46709024-9b23ad00-cbf6-11e8-9fb2-ca8b20b7dbec.jpg"
width="408px" border="0" alt="croc">
<br>
<a href="https://github.com/schollz/croc/releases/latest"><img src="https://img.shields.io/badge/version-v10.0.9-brightgreen.svg?style=flat-square" alt="Version"></a>
<a href="https://github.com/schollz/croc/releases/latest"><img src="https://img.shields.io/badge/version-v10.1.1-brightgreen.svg?style=flat-square" alt="Version"></a>
<a href="https://github.com/schollz/croc/actions/workflows/ci.yml"><img
src="https://github.com/schollz/croc/actions/workflows/ci.yml/badge.svg" alt="Build
Status"></a>
@ -104,7 +104,19 @@ On FreeBSD you can install with `pkg`:
pkg install croc
```
Or, you can [install Go](https://golang.org/dl/) and build from source (requires Go 1.17+):
On Linux, macOS, and Windows you can install from [conda-forge](https://github.com/conda-forge/croc-feedstock/) globally with [`pixi`](https://pixi.sh/):
```
pixi global install croc
```
or into a particular environment with [`conda`](https://docs.conda.io/projects/conda/):
```
conda install --channel conda-forge croc
```
Or, you can [install Go](https://golang.org/dl/) and build from source (requires Go 1.17+):
```
go install github.com/schollz/croc/v10@latest
@ -113,7 +125,7 @@ go install github.com/schollz/croc/v10@latest
On Android there is a 3rd party F-Droid app [available to download](https://f-droid.org/en/packages/com.github.howeyc.crocgui/).
## Usage
## Usage
To send a file, simply do:
@ -133,6 +145,25 @@ The code phrase is used to establish password-authenticated key agreement ([PAKE
There are a number of configurable options (see `--help`). A set of options (like custom relay, ports, and code phrase) can be set using `--remember`.
### Using `croc` on Linux or Mac OS
On Linux and Mac OS, the sending & receiving is slightly different to avoid [leaking the secret via the process name](https://nvd.nist.gov/vuln/detail/CVE-2023-43621). On these systems you will need to run `croc` with the secret as an environment variable. For example, to receive with the secret `***`:
```
CROC_SECRET=*** croc
```
This will show only `croc` in the process list of a multi-user system and not leak the secret.
For a single-user system the default behavior can be permanently enabled by running
```
croc --classic
```
and confirming.
Run this command again to disable classic mode.
### Custom code phrase
You can send with your own code phrase (must be more than 6 characters).
@ -167,7 +198,7 @@ croc --yes [code-phrase] > out
All of the other text printed to the console is going to `stderr` so it will not interfere with the message going to `stdout`.
### Send text
### Send text
Sometimes you want to send URLs or short text. In addition to piping, you can easily send text with `croc`:

33
go.mod
View File

@ -1,42 +1,39 @@
module github.com/schollz/croc/v10
go 1.20
go 1.22
toolchain go1.23.1
require (
github.com/cespare/xxhash v1.1.0
github.com/chzyer/readline v1.5.1
github.com/denisbrodbeck/machineid v1.0.1
github.com/kalafut/imohash v1.0.4
github.com/kalafut/imohash v1.1.0
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b
github.com/minio/highwayhash v1.0.3
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/schollz/cli/v2 v2.2.1
github.com/schollz/logger v1.2.0
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d
github.com/schollz/pake/v3 v3.0.5
github.com/schollz/peerdiscovery v1.7.3
github.com/schollz/progressbar/v3 v3.14.4
github.com/schollz/peerdiscovery v1.7.5
github.com/schollz/progressbar/v3 v3.17.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.24.0
golang.org/x/net v0.26.0
golang.org/x/time v0.5.0
golang.org/x/crypto v0.29.0
golang.org/x/net v0.31.0
golang.org/x/sys v0.27.0
golang.org/x/term v0.26.0
golang.org/x/time v0.8.0
)
require github.com/minio/highwayhash v1.0.2
require (
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

89
go.sum
View File

@ -1,9 +1,10 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chengxilo/virtualterm v1.0.4 h1:Z6IpERbRVlfB8WkOmtbHiDbBANU7cimRIof7mk9/PwM=
github.com/chengxilo/virtualterm v1.0.4/go.mod h1:DyxxBZz/x1iqJjFxTFcr6/x+jSpqN0iwWCOK1q10rlY=
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
@ -11,26 +12,22 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kalafut/imohash v1.0.4 h1:3B5ecu2k6KhLnkXFvBJBgEtiOYzMw4oKXvflJe0JkPA=
github.com/kalafut/imohash v1.0.4/go.mod h1:6cn9lU0Sj8M4eu9UaQm1kR/5y3k/ayB68yntRhGloL4=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/kalafut/imohash v1.1.0 h1:Lldcmx0SXgMSoABB2WBD8mTgf0OlVnISn2Dyrfg2Ep8=
github.com/kalafut/imohash v1.1.0/go.mod h1:6cn9lU0Sj8M4eu9UaQm1kR/5y3k/ayB68yntRhGloL4=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -46,20 +43,18 @@ github.com/schollz/cli/v2 v2.2.1 h1:ou22Mj7ZPjrKz+8k2iDTWaHskEEV5NiAxGrdsCL36VU=
github.com/schollz/cli/v2 v2.2.1/go.mod h1:My6bfphRLZUhZdlFUK8scAxMWHydE7k4s2ed2Dtnn+s=
github.com/schollz/logger v1.2.0 h1:5WXfINRs3lEUTCZ7YXhj0uN+qukjizvITLm3Ca2m0Ho=
github.com/schollz/logger v1.2.0/go.mod h1:P6F4/dGMGcx8wh+kG1zrNEd4vnNpEBY/mwEMd/vn6AM=
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d h1:3zCjdgCJbo9Fot3UoqZkpGiDgT6Nf+iUnOsDEJQay+c=
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d/go.mod h1:cl4UAOhUV0mkdjMj/QYaUZbZZdF8BnOqoz8rHMzwboY=
github.com/schollz/pake/v3 v3.0.5 h1:MnZVdI987lkjln9BSx/zUb724TZISa2jbO+dPj6BvgQ=
github.com/schollz/pake/v3 v3.0.5/go.mod h1:OGbG6htRwSKo6V8R5tg61ufpFmZM1b/PrrSp6g2ZLLc=
github.com/schollz/peerdiscovery v1.7.3 h1:/pt1G0rZ80fSPoI/FgGC5P7MxpkRXD6u0pe6PJbYcIE=
github.com/schollz/peerdiscovery v1.7.3/go.mod h1:mVlPNJ5DWbMi52VzpXxGbqXKdFANx3qw0Jsp3EQMCrE=
github.com/schollz/progressbar/v3 v3.14.4 h1:W9ZrDSJk7eqmQhd3uxFNNcTr0QL+xuGNI9dEMrw0r74=
github.com/schollz/progressbar/v3 v3.14.4/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/schollz/peerdiscovery v1.7.5 h1:0cEhO+o8i4fpeKBwl7u0UY3Kt3XVt5fSzS4rg17ZPb4=
github.com/schollz/peerdiscovery v1.7.5/go.mod h1:Crht2FOfD1/eL3U/AIM0vvwVZDPePlBgSX3Xw+TnJoE=
github.com/schollz/progressbar/v3 v3.17.1 h1:bI1MTaoQO+v5kzklBjYNRQLoVpe0zbyRZNK6DFkVC5U=
github.com/schollz/progressbar/v3 v3.17.1/go.mod h1:RzqpnsPQNjUyIgdglUjRLgD7sVnxN1wpmBMV+UiEbL4=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
@ -72,25 +67,35 @@ github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
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=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
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=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -98,39 +103,45 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

30
main.go
View File

@ -5,9 +5,13 @@ package main
//go:generate git tag -af v$VERSION -m "v$VERSION"
import (
"log"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/schollz/croc/v10/src/cli"
"github.com/schollz/croc/v10/src/utils"
)
func main() {
@ -27,7 +31,25 @@ func main() {
// fmt.Println("wrote profile")
// }
// }()
if err := cli.Run(); err != nil {
log.Fatalln(err)
}
// Create a channel to receive OS signals
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
go func() {
if err := cli.Run(); err != nil {
fmt.Println(err)
os.Exit(1)
}
// Exit the program gracefully
utils.RemoveMarkedFiles()
os.Exit(0)
}()
// Wait for a termination signal
_ = <-sigs
utils.RemoveMarkedFiles()
// Exit the program gracefully
os.Exit(0)
}

View File

@ -17,11 +17,11 @@ import (
"github.com/schollz/cli/v2"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/croc"
"github.com/schollz/croc/v10/src/mnemonicode"
"github.com/schollz/croc/v10/src/models"
"github.com/schollz/croc/v10/src/tcp"
"github.com/schollz/croc/v10/src/utils"
log "github.com/schollz/logger"
"github.com/schollz/mnemonicode"
"github.com/schollz/pake/v3"
)
@ -36,7 +36,7 @@ func Run() (err error) {
app := cli.NewApp()
app.Name = "croc"
if Version == "" {
Version = "v10.0.9"
Version = "v10.1.0"
}
app.Version = Version
app.Compiled = time.Now()
@ -77,6 +77,7 @@ func Run() (err error) {
&cli.BoolFlag{Name: "git", Usage: "enable .gitignore respect / don't send ignored files"},
&cli.IntFlag{Name: "port", Value: 9009, Usage: "base port for the relay"},
&cli.IntFlag{Name: "transfers", Value: 4, Usage: "number of ports to use for transfers"},
&cli.BoolFlag{Name: "qrcode", Aliases: []string{"qr"}, Usage: "show receive code as a qrcode"},
},
HelpName: "croc send",
Action: send,
@ -90,6 +91,8 @@ func Run() (err error) {
Flags: []cli.Flag{
&cli.StringFlag{Name: "host", Usage: "host of the relay"},
&cli.StringFlag{Name: "ports", Value: "9009,9010,9011,9012,9013", Usage: "ports of the relay"},
&cli.IntFlag{Name: "port", Value: 9009, Usage: "base port for the relay"},
&cli.IntFlag{Name: "transfers", Value: 5, Usage: "number of ports to use for relay"},
},
},
}
@ -106,6 +109,7 @@ func Run() (err error) {
&cli.BoolFlag{Name: "ignore-stdin", Usage: "ignore piped stdin"},
&cli.BoolFlag{Name: "overwrite", Usage: "do not prompt to overwrite or resume"},
&cli.BoolFlag{Name: "testing", Usage: "flag for testing purposes"},
&cli.StringFlag{Name: "multicast", Value: "239.255.255.250", Usage: "multicast address to use for local discovery"},
&cli.StringFlag{Name: "curve", Value: "p256", Usage: "choose an encryption curve (" + strings.Join(pake.AvailableCurves(), ", ") + ")"},
&cli.StringFlag{Name: "ip", Value: "", Usage: "set sender ip if known e.g. 10.0.0.1:9009, [::1]:9009"},
&cli.StringFlag{Name: "relay", Value: models.DEFAULT_RELAY, Usage: "address of the relay", EnvVars: []string{"CROC_RELAY"}},
@ -167,7 +171,7 @@ on the host's process list when passed via the command line. On a
multi-user system, this could allow other local users to access the
shared secret and receive the files instead of the intended recipient.
Do you wish to continue to enable the classic mode? (Y/n) `)
Do you wish to continue to enable the classic mode? (y/N) `)
choice := strings.ToLower(utils.GetInput(""))
if choice == "y" || choice == "yes" {
fmt.Print("\nClassic mode ENABLED.\n\n")
@ -208,6 +212,14 @@ func setDebugLevel(c *cli.Context) {
if c.Bool("debug") {
log.SetLevel("debug")
log.Debug("debug mode on")
// print the public IP address
ip, err := utils.PublicIP()
if err == nil {
log.Debugf("public IP address: %s", ip)
} else {
log.Debug(err)
}
} else {
log.SetLevel("info")
}
@ -269,28 +281,30 @@ func send(c *cli.Context) (err error) {
}
crocOptions := croc.Options{
SharedSecret: c.String("code"),
IsSender: true,
Debug: c.Bool("debug"),
NoPrompt: c.Bool("yes"),
RelayAddress: c.String("relay"),
RelayAddress6: c.String("relay6"),
Stdout: c.Bool("stdout"),
DisableLocal: c.Bool("no-local"),
OnlyLocal: c.Bool("local"),
IgnoreStdin: c.Bool("ignore-stdin"),
RelayPorts: ports,
Ask: c.Bool("ask"),
NoMultiplexing: c.Bool("no-multi"),
RelayPassword: determinePass(c),
SendingText: c.String("text") != "",
NoCompress: c.Bool("no-compress"),
Overwrite: c.Bool("overwrite"),
Curve: c.String("curve"),
HashAlgorithm: c.String("hash"),
ThrottleUpload: c.String("throttleUpload"),
ZipFolder: c.Bool("zip"),
GitIgnore: c.Bool("git"),
SharedSecret: c.String("code"),
IsSender: true,
Debug: c.Bool("debug"),
NoPrompt: c.Bool("yes"),
RelayAddress: c.String("relay"),
RelayAddress6: c.String("relay6"),
Stdout: c.Bool("stdout"),
DisableLocal: c.Bool("no-local"),
OnlyLocal: c.Bool("local"),
IgnoreStdin: c.Bool("ignore-stdin"),
RelayPorts: ports,
Ask: c.Bool("ask"),
NoMultiplexing: c.Bool("no-multi"),
RelayPassword: determinePass(c),
SendingText: c.String("text") != "",
NoCompress: c.Bool("no-compress"),
Overwrite: c.Bool("overwrite"),
Curve: c.String("curve"),
HashAlgorithm: c.String("hash"),
ThrottleUpload: c.String("throttleUpload"),
ZipFolder: c.Bool("zip"),
GitIgnore: c.Bool("git"),
ShowQrCode: c.Bool("qrcode"),
MulticastAddress: c.String("multicast"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
@ -348,6 +362,7 @@ func send(c *cli.Context) (err error) {
if err != nil {
return
}
utils.MarkFileForRemoval(fnames[0])
defer func() {
e := os.Remove(fnames[0])
if e != nil {
@ -359,6 +374,7 @@ func send(c *cli.Context) (err error) {
if err != nil {
return
}
utils.MarkFileForRemoval(fnames[0])
defer func() {
e := os.Remove(fnames[0])
if e != nil {
@ -382,10 +398,9 @@ func send(c *cli.Context) (err error) {
fmt.Printf(`On UNIX systems, to send with a custom code phrase,
you need to set the environmental variable CROC_SECRET:
export CROC_SECRET="****"
croc send file.txt
CROC_SECRET=**** croc send file.txt
Or you can have the code phrase automaticlaly generated:
Or you can have the code phrase automatically generated:
croc send file.txt
@ -514,20 +529,21 @@ func receive(c *cli.Context) (err error) {
comm.Socks5Proxy = c.String("socks5")
comm.HttpProxy = c.String("connect")
crocOptions := croc.Options{
SharedSecret: c.String("code"),
IsSender: false,
Debug: c.Bool("debug"),
NoPrompt: c.Bool("yes"),
RelayAddress: c.String("relay"),
RelayAddress6: c.String("relay6"),
Stdout: c.Bool("stdout"),
Ask: c.Bool("ask"),
RelayPassword: determinePass(c),
OnlyLocal: c.Bool("local"),
IP: c.String("ip"),
Overwrite: c.Bool("overwrite"),
Curve: c.String("curve"),
TestFlag: c.Bool("testing"),
SharedSecret: c.String("code"),
IsSender: false,
Debug: c.Bool("debug"),
NoPrompt: c.Bool("yes"),
RelayAddress: c.String("relay"),
RelayAddress6: c.String("relay6"),
Stdout: c.Bool("stdout"),
Ask: c.Bool("ask"),
RelayPassword: determinePass(c),
OnlyLocal: c.Bool("local"),
IP: c.String("ip"),
Overwrite: c.Bool("overwrite"),
Curve: c.String("curve"),
TestFlag: c.Bool("testing"),
MulticastAddress: c.String("multicast"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
@ -599,8 +615,7 @@ func receive(c *cli.Context) (err error) {
fmt.Printf(`On UNIX systems, to receive with croc you either need
to set a code phrase using your environmental variables:
export CROC_SECRET="****"
croc
CROC_SECRET=**** croc
Or you can specify the code phrase when you run croc without
declaring the secret on the command line:
@ -668,7 +683,25 @@ func relay(c *cli.Context) (err error) {
debugString = "debug"
}
host := c.String("host")
ports := strings.Split(c.String("ports"), ",")
var ports []string
if c.IsSet("ports") {
ports = strings.Split(c.String("ports"), ",")
} else {
portString := c.Int("port")
if portString == 0 {
portString = 9009
}
transfersString := c.Int("transfers")
if transfersString == 0 {
transfersString = 4
}
ports = make([]string, transfersString)
for i := range ports {
ports[i] = strconv.Itoa(portString + i)
}
}
tcpPorts := strings.Join(ports[1:], ",")
for i, port := range ports {
if i == 0 {

View File

@ -12,21 +12,24 @@ import (
"math"
"net"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"
"time"
"golang.org/x/time/rate"
"github.com/denisbrodbeck/machineid"
ignore "github.com/sabhiram/go-gitignore"
log "github.com/schollz/logger"
"github.com/schollz/pake/v3"
"github.com/schollz/peerdiscovery"
"github.com/schollz/progressbar/v3"
"github.com/skip2/go-qrcode"
"golang.org/x/term"
"golang.org/x/time/rate"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/compress"
@ -57,31 +60,33 @@ func Debug(debug bool) {
// Options specifies user specific options
type Options struct {
IsSender bool
SharedSecret string
RoomName string
Debug bool
RelayAddress string
RelayAddress6 string
RelayPorts []string
RelayPassword string
Stdout bool
NoPrompt bool
NoMultiplexing bool
DisableLocal bool
OnlyLocal bool
IgnoreStdin bool
Ask bool
SendingText bool
NoCompress bool
IP string
Overwrite bool
Curve string
HashAlgorithm string
ThrottleUpload string
ZipFolder bool
TestFlag bool
GitIgnore bool
IsSender bool
SharedSecret string
RoomName string
Debug bool
RelayAddress string
RelayAddress6 string
RelayPorts []string
RelayPassword string
Stdout bool
NoPrompt bool
NoMultiplexing bool
DisableLocal bool
OnlyLocal bool
IgnoreStdin bool
Ask bool
SendingText bool
NoCompress bool
IP string
Overwrite bool
Curve string
HashAlgorithm string
ThrottleUpload string
ZipFolder bool
TestFlag bool
GitIgnore bool
MulticastAddress string
ShowQrCode bool
}
type SimpleMessage struct {
@ -225,8 +230,8 @@ func New(ops Options) (c *Client, err error) {
panic("Could not parse given Upload Limit")
}
}
// Somehow 4* is necessary
rt = rate.Every(time.Second / (4 * time.Duration(uploadLimit)))
rt = rate.Every(time.Second / time.Duration(uploadLimit))
if int(uploadLimit) > minBurstSize {
minBurstSize = int(uploadLimit)
}
@ -305,7 +310,6 @@ func isChild(parentPath, childPath string) bool {
return false
}
return !strings.HasPrefix(relPath, "..")
}
// This function retrieves the important file information
@ -328,7 +332,7 @@ func GetFilesInfo(fnames []string, zipfolder bool, ignoreGit bool) (filesInfo []
paths = append(paths, fname)
}
}
var ignoredPaths = make(map[string]bool)
ignoredPaths := make(map[string]bool)
if ignoreGit {
wd, wdErr := os.Stat(".gitignore")
if wdErr == nil {
@ -387,6 +391,7 @@ func GetFilesInfo(fnames []string, zipfolder bool, ignoreGit bool) (filesInfo []
fpath = filepath.Dir(fpath)
dest := filepath.Base(fpath) + ".zip"
utils.ZipDirectory(dest, fpath)
utils.MarkFileForRemoval(dest)
stat, errStat = os.Lstat(dest)
if errStat != nil {
err = errStat
@ -421,8 +426,14 @@ func GetFilesInfo(fnames []string, zipfolder bool, ignoreGit bool) (filesInfo []
if err != nil {
return err
}
remoteFolder := strings.TrimPrefix(filepath.Dir(pathName),
filepath.Dir(absPath)+string(os.PathSeparator))
absPathWithSeparator := filepath.Dir(absPath)
if !strings.HasSuffix(absPathWithSeparator, string(os.PathSeparator)) {
absPathWithSeparator += string(os.PathSeparator)
}
if strings.HasSuffix(absPathWithSeparator, string(os.PathSeparator)+string(os.PathSeparator)) {
absPathWithSeparator = strings.TrimSuffix(absPathWithSeparator, string(os.PathSeparator))
}
remoteFolder := strings.TrimPrefix(filepath.Dir(pathName), absPathWithSeparator)
if !info.IsDir() {
fInfo := FileInfo{
Name: info.Name(),
@ -579,6 +590,8 @@ func (c *Client) broadcastOnLocalNetwork(useipv6 bool) {
}
if useipv6 {
settings.IPVersion = peerdiscovery.IPv6
} else {
settings.MulticastAddress = c.Options.MulticastAddress
}
discoveries, err := peerdiscovery.Discover(settings)
@ -640,7 +653,18 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
if c.Options.RelayPassword != models.DEFAULT_PASSPHRASE {
flags.WriteString("--pass " + c.Options.RelayPassword + " ")
}
fmt.Fprintf(os.Stderr, "Code is: %[1]s\nOn the other computer run\n\ncroc %[2]s%[1]s\n", c.Options.SharedSecret, flags.String())
fmt.Fprintf(os.Stderr, `Code is: %[1]s
On the other computer run:
(For Windows)
croc %[2]s%[1]s
(For Linux/OSX)
CROC_SECRET=%[1]q croc %[2]s
`, c.Options.SharedSecret, flags.String())
copyToClipboard(c.Options.SharedSecret)
if c.Options.ShowQrCode {
showReceiveCommandQrCode(fmt.Sprintf("%[1]s", c.Options.SharedSecret))
}
if c.Options.Ask {
machid, _ := machineid.ID()
fmt.Fprintf(os.Stderr, "\rYour machine ID is '%s'\n", machid)
@ -813,6 +837,13 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
return err
}
func showReceiveCommandQrCode(command string) {
qrCode, err := qrcode.New(command, qrcode.Medium)
if err == nil {
fmt.Println(qrCode.ToSmallString(false))
}
}
// Receive will receive a file
func (c *Client) Receive() (err error) {
fmt.Fprintf(os.Stderr, "connecting...")
@ -848,10 +879,11 @@ func (c *Client) Receive() (err error) {
go func() {
defer wgDiscovery.Done()
ipv4discoveries, err1 := peerdiscovery.Discover(peerdiscovery.Settings{
Limit: 1,
Payload: []byte("ok"),
Delay: 20 * time.Millisecond,
TimeLimit: 200 * time.Millisecond,
Limit: 1,
Payload: []byte("ok"),
Delay: 20 * time.Millisecond,
TimeLimit: 200 * time.Millisecond,
MulticastAddress: c.Options.MulticastAddress,
})
if err1 == nil && len(ipv4discoveries) > 0 {
dmux.Lock()
@ -1202,7 +1234,16 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
for i, fi := range c.FilesToTransfer {
// Issues #593 - sanitize the sender paths and prevent ".." from being used
c.FilesToTransfer[i].FolderRemote = filepath.Clean(fi.FolderRemote)
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "..") {
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "../") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "/..") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "\\..") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "..\\") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
// Issues #593 - disallow specific folders like .ssh
@ -1252,6 +1293,12 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
}
}
}
// // check the totalSize does not exceed disk space
// usage := diskusage.NewDiskUsage(".")
// if usage.Available() < uint64(totalSize) {
// return true, fmt.Errorf("not enough disk space")
// }
// c.spinner.Stop()
action := "Accept"
if c.Options.SendingText {
@ -1675,6 +1722,25 @@ func (c *Client) recipientGetFileReady(finished bool) (err error) {
return
}
func max(a int, b int) int {
if a > b {
return a
}
return b
}
func formatDescription(description string) string {
width, _, err := term.GetSize(int(os.Stdout.Fd()))
width = max(20, width-60)
if err != nil {
return description
}
if len(description) > width {
description = description[:(width-3)] + "..."
}
return description
}
func (c *Client) createEmptyFileAndFinish(fileInfo FileInfo, i int) (err error) {
log.Debugf("touching file with folder / name")
if !utils.Exists(fileInfo.FolderRemote) {
@ -1712,15 +1778,12 @@ func (c *Client) createEmptyFileAndFinish(fileInfo FileInfo, i int) (err error)
} else {
description = " " + description
}
if len(description) > 20 {
description = description[:17] + "..."
}
c.bar = progressbar.NewOptions64(1,
progressbar.OptionOnCompletion(func() {
c.fmtPrintUpdate()
}),
progressbar.OptionSetWidth(20),
progressbar.OptionSetDescription(description),
progressbar.OptionSetDescription(formatDescription(description)),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
@ -1844,12 +1907,13 @@ func (c *Client) updateState() (err error) {
description = c.FilesToTransfer[i].Name
// description = ""
}
c.bar = progressbar.NewOptions64(1,
progressbar.OptionOnCompletion(func() {
c.fmtPrintUpdate()
}),
progressbar.OptionSetWidth(20),
progressbar.OptionSetDescription(description),
progressbar.OptionSetDescription(formatDescription(description)),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
@ -1891,16 +1955,13 @@ func (c *Client) setBar() {
} else if !c.Options.IsSender {
description = " " + description
}
if len(description) > 20 {
description = description[:17] + "..."
}
c.bar = progressbar.NewOptions64(
c.FilesToTransfer[c.FilesToTransferCurrentNum].Size,
progressbar.OptionOnCompletion(func() {
c.fmtPrintUpdate()
}),
progressbar.OptionSetWidth(20),
progressbar.OptionSetDescription(description),
progressbar.OptionSetDescription(formatDescription(description)),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionShowBytes(true),
progressbar.OptionShowCount(),
@ -2075,3 +2136,27 @@ 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")
}

View File

@ -232,7 +232,7 @@ func TestCrocSymlink(t *testing.T) {
t.Errorf("symlink transfer failed: %s", err.Error())
}
}
func testCrocIgnoreGit(t *testing.T) {
func TestCrocIgnoreGit(t *testing.T) {
log.SetLevel("trace")
defer os.Remove(".gitignore")
time.Sleep(300 * time.Millisecond)

View File

@ -24,6 +24,20 @@ func BenchmarkDecrypt(b *testing.B) {
}
}
func BenchmarkNewPbkdf2(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
New([]byte("password"), nil)
}
}
func BenchmarkNewArgon2(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
NewArgon2([]byte("password"), nil)
}
}
func BenchmarkEncryptChaCha(b *testing.B) {
bob, _, _ := NewArgon2([]byte("password"), nil)
for i := 0; i < b.N; i++ {

View File

@ -0,0 +1,49 @@
//go:build !windows
// +build !windows
package diskusage
import (
"golang.org/x/sys/unix"
)
// DiskUsage contains usage data and provides user-friendly access methods
type DiskUsage struct {
stat *unix.Statfs_t
}
// NewDiskUsage returns an object holding the disk usage of volumePath
// or nil in case of error (invalid path, etc)
func NewDiskUsage(volumePath string) *DiskUsage {
stat := unix.Statfs_t{}
err := unix.Statfs(volumePath, &stat)
if err != nil {
return nil
}
return &DiskUsage{&stat}
}
// Free returns total free bytes on file system
func (du *DiskUsage) Free() uint64 {
return uint64(du.stat.Bfree) * uint64(du.stat.Bsize)
}
// Available return total available bytes on file system to an unprivileged user
func (du *DiskUsage) Available() uint64 {
return uint64(du.stat.Bavail) * uint64(du.stat.Bsize)
}
// Size returns total size of the file system
func (du *DiskUsage) Size() uint64 {
return uint64(du.stat.Blocks) * uint64(du.stat.Bsize)
}
// Used returns total bytes used in file system
func (du *DiskUsage) Used() uint64 {
return du.Size() - du.Free()
}
// Usage returns percentage of use on the file system
func (du *DiskUsage) Usage() float32 {
return float32(du.Used()) / float32(du.Size())
}

View File

@ -0,0 +1,17 @@
package diskusage
import (
"fmt"
"testing"
)
var KB = uint64(1024)
func TestNewDiskUsage(t *testing.T) {
usage := NewDiskUsage(".")
fmt.Println("Free:", usage.Free()/(KB*KB))
fmt.Println("Available:", usage.Available()/(KB*KB))
fmt.Println("Size:", usage.Size()/(KB*KB))
fmt.Println("Used:", usage.Used()/(KB*KB))
fmt.Println("Usage:", usage.Usage()*100, "%")
}

View File

@ -0,0 +1,55 @@
package diskusage
import (
"unsafe"
"golang.org/x/sys/windows"
)
type DiskUsage struct {
freeBytes int64
totalBytes int64
availBytes int64
}
// NewDiskUsage returns an object holding the disk usage of volumePath
// or nil in case of error (invalid path, etc)
func NewDiskUsage(volumePath string) *DiskUsage {
h := windows.MustLoadDLL("kernel32.dll")
c := h.MustFindProc("GetDiskFreeSpaceExW")
du := &DiskUsage{}
c.Call(
uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(volumePath))),
uintptr(unsafe.Pointer(&du.freeBytes)),
uintptr(unsafe.Pointer(&du.totalBytes)),
uintptr(unsafe.Pointer(&du.availBytes)))
return du
}
// Free returns total free bytes on file system
func (du *DiskUsage) Free() uint64 {
return uint64(du.freeBytes)
}
// Available returns total available bytes on file system to an unprivileged user
func (du *DiskUsage) Available() uint64 {
return uint64(du.availBytes)
}
// Size returns total size of the file system
func (du *DiskUsage) Size() uint64 {
return uint64(du.totalBytes)
}
// Used returns total bytes used in file system
func (du *DiskUsage) Used() uint64 {
return du.Size() - du.Free()
}
// Usage returns percentage of use on the file system
func (du *DiskUsage) Usage() float32 {
return float32(du.Used()) / float32(du.Size())
}

View File

@ -528,7 +528,7 @@ main() {
local autocomplete_install_rcode
croc_bin_name="croc"
croc_version="10.0.9"
croc_version="10.1.1"
croc_dl_ext="tar.gz"
croc_base_url="https://github.com/schollz/croc/releases/download"
prefix="${1}"
@ -577,6 +577,9 @@ main() {
case "${croc_os}" in
"Darwin" ) croc_os="macOS";;
*"BusyBox"* )
croc_os="Linux"
;;
"CYGWIN"* ) croc_os="Windows";
croc_dl_ext="zip";
print_message "== Cygwin is currently unsupported." "error";
@ -589,6 +592,8 @@ main() {
"aarch64" ) croc_arch="ARM64";;
"arm64" ) croc_arch="ARM64";;
"armv7l" ) croc_arch="ARM";;
"armv8l" ) croc_arch="ARM";;
"armv9l" ) croc_arch="ARM";;
"i686" ) croc_arch="32bit";;
* ) croc_arch="unknown";;
esac
@ -685,7 +690,7 @@ main() {
print_message "== Install prefix already exists. No need to create it." "info"
fi
[ ! -d "/etc/bash_completion.d/croc" ] && mkdir -p "/etc/bash_completion.d/croc"
[ ! -d "${bash_autocomplete_prefix}/croc" ] && mkdir -p "${bash_autocomplete_prefix}/croc" >/dev/null 2>&1
case "${croc_os}" in
"Linux" ) install_file_linux "${tmpdir}/${croc_bin_name}" "${prefix}/";
install_file_rcode="${?}";;

View File

@ -0,0 +1,88 @@
// From GitHub version/fork maintained by Stephen Paul Weber available at:
// https://github.com/singpolyma/mnemonicode
//
// Originally from:
// http://web.archive.org/web/20101031205747/http://www.tothink.com/mnemonic/
/*
Copyright (c) 2000 Oren Tirosh <oren@hishome.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package mnemonicode
const base = 1626
// WordsRequired returns the number of words required to encode input
// data of length bytes using mnomonic encoding.
//
// Every four bytes of input is encoded into three words. If there
// is an extra one or two bytes they get an extra one or two words
// respectively. If there is an extra three bytes, they will be encoded
// into three words with the last word being one of a small set of very
// short words (only needed to encode the last 3 bits).
func WordsRequired(length int) int {
return ((length + 1) * 3) / 4
}
// EncodeWordList encodes src into mnemomic words which are appended to dst.
// The final wordlist is returned.
// There will be WordsRequired(len(src)) words appeneded.
func EncodeWordList(dst []string, src []byte) (result []string) {
if n := len(dst) + WordsRequired(len(src)); cap(dst) < n {
result = make([]string, len(dst), n)
copy(result, dst)
} else {
result = dst
}
var x uint32
for len(src) >= 4 {
x = uint32(src[0])
x |= uint32(src[1]) << 8
x |= uint32(src[2]) << 16
x |= uint32(src[3]) << 24
src = src[4:]
i0 := int(x % base)
i1 := int(x/base) % base
i2 := int(x/base/base) % base
result = append(result, WordList[i0], WordList[i1], WordList[i2])
}
if len(src) > 0 {
x = 0
for i := len(src) - 1; i >= 0; i-- {
x <<= 8
x |= uint32(src[i])
}
i := int(x % base)
result = append(result, WordList[i])
if len(src) >= 2 {
i = int(x/base) % base
result = append(result, WordList[i])
}
if len(src) == 3 {
i = base + int(x/base/base)%7
result = append(result, WordList[i])
}
}
return result
}

318
src/mnemonicode/wordlist.go Normal file
View File

@ -0,0 +1,318 @@
// From GitHub version/fork maintained by Stephen Paul Weber available at:
// https://github.com/singpolyma/mnemonicode
//
// Originally from:
// http://web.archive.org/web/20101031205747/http://www.tothink.com/mnemonic/
/*
Copyright (c) 2000 Oren Tirosh <oren@hishome.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package mnemonicode
// WordListVersion is the version of compiled in word list.
const WordListVersion = "0.7"
var wordMap = make(map[string]int, len(WordList))
func init() {
for i, w := range WordList {
wordMap[w] = i
}
}
const longestWord = 7
var WordList = []string{
"academy", "acrobat", "active", "actor", "adam", "admiral",
"adrian", "africa", "agenda", "agent", "airline", "airport",
"aladdin", "alarm", "alaska", "albert", "albino", "album",
"alcohol", "alex", "algebra", "alibi", "alice", "alien",
"alpha", "alpine", "amadeus", "amanda", "amazon", "amber",
"america", "amigo", "analog", "anatomy", "angel", "animal",
"antenna", "antonio", "apollo", "april", "archive", "arctic",
"arizona", "arnold", "aroma", "arthur", "artist", "asia",
"aspect", "aspirin", "athena", "athlete", "atlas", "audio",
"august", "austria", "axiom", "aztec", "balance", "ballad",
"banana", "bandit", "banjo", "barcode", "baron", "basic",
"battery", "belgium", "berlin", "bermuda", "bernard", "bikini",
"binary", "bingo", "biology", "block", "blonde", "bonus",
"boris", "boston", "boxer", "brandy", "bravo", "brazil",
"bronze", "brown", "bruce", "bruno", "burger", "burma",
"cabinet", "cactus", "cafe", "cairo", "cake", "calypso",
"camel", "camera", "campus", "canada", "canal", "cannon",
"canoe", "cantina", "canvas", "canyon", "capital", "caramel",
"caravan", "carbon", "cargo", "carlo", "carol", "carpet",
"cartel", "casino", "castle", "castro", "catalog", "caviar",
"cecilia", "cement", "center", "century", "ceramic", "chamber",
"chance", "change", "chaos", "charlie", "charm", "charter",
"chef", "chemist", "cherry", "chess", "chicago", "chicken",
"chief", "china", "cigar", "cinema", "circus", "citizen",
"city", "clara", "classic", "claudia", "clean", "client",
"climax", "clinic", "clock", "club", "cobra", "coconut",
"cola", "collect", "colombo", "colony", "color", "combat",
"comedy", "comet", "command", "compact", "company", "complex",
"concept", "concert", "connect", "consul", "contact", "context",
"contour", "control", "convert", "copy", "corner", "corona",
"correct", "cosmos", "couple", "courage", "cowboy", "craft",
"crash", "credit", "cricket", "critic", "crown", "crystal",
"cuba", "culture", "dallas", "dance", "daniel", "david",
"decade", "decimal", "deliver", "delta", "deluxe", "demand",
"demo", "denmark", "derby", "design", "detect", "develop",
"diagram", "dialog", "diamond", "diana", "diego", "diesel",
"diet", "digital", "dilemma", "diploma", "direct", "disco",
"disney", "distant", "doctor", "dollar", "dominic", "domino",
"donald", "dragon", "drama", "dublin", "duet", "dynamic",
"east", "ecology", "economy", "edgar", "egypt", "elastic",
"elegant", "element", "elite", "elvis", "email", "energy",
"engine", "english", "episode", "equator", "escort", "ethnic",
"europe", "everest", "evident", "exact", "example", "exit",
"exotic", "export", "express", "extra", "fabric", "factor",
"falcon", "family", "fantasy", "fashion", "fiber", "fiction",
"fidel", "fiesta", "figure", "film", "filter", "final",
"finance", "finish", "finland", "flash", "florida", "flower",
"fluid", "flute", "focus", "ford", "forest", "formal",
"format", "formula", "fortune", "forum", "fragile", "france",
"frank", "friend", "frozen", "future", "gabriel", "galaxy",
"gallery", "gamma", "garage", "garden", "garlic", "gemini",
"general", "genetic", "genius", "germany", "global", "gloria",
"golf", "gondola", "gong", "good", "gordon", "gorilla",
"grand", "granite", "graph", "green", "group", "guide",
"guitar", "guru", "hand", "happy", "harbor", "harmony",
"harvard", "havana", "hawaii", "helena", "hello", "henry",
"hilton", "history", "horizon", "hotel", "human", "humor",
"icon", "idea", "igloo", "igor", "image", "impact",
"import", "index", "india", "indigo", "input", "insect",
"instant", "iris", "italian", "jacket", "jacob", "jaguar",
"janet", "japan", "jargon", "jazz", "jeep", "john",
"joker", "jordan", "jumbo", "june", "jungle", "junior",
"jupiter", "karate", "karma", "kayak", "kermit", "kilo",
"king", "koala", "korea", "labor", "lady", "lagoon",
"laptop", "laser", "latin", "lava", "lecture", "left",
"legal", "lemon", "level", "lexicon", "liberal", "libra",
"limbo", "limit", "linda", "linear", "lion", "liquid",
"liter", "little", "llama", "lobby", "lobster", "local",
"logic", "logo", "lola", "london", "lotus", "lucas",
"lunar", "machine", "macro", "madam", "madonna", "madrid",
"maestro", "magic", "magnet", "magnum", "major", "mama",
"mambo", "manager", "mango", "manila", "marco", "marina",
"market", "mars", "martin", "marvin", "master", "matrix",
"maximum", "media", "medical", "mega", "melody", "melon",
"memo", "mental", "mentor", "menu", "mercury", "message",
"metal", "meteor", "meter", "method", "metro", "mexico",
"miami", "micro", "million", "mineral", "minimum", "minus",
"minute", "miracle", "mirage", "miranda", "mister", "mixer",
"mobile", "model", "modem", "modern", "modular", "moment",
"monaco", "monica", "monitor", "mono", "monster", "montana",
"morgan", "motel", "motif", "motor", "mozart", "multi",
"museum", "music", "mustang", "natural", "neon", "nepal",
"neptune", "nerve", "neutral", "nevada", "news", "ninja",
"nirvana", "normal", "nova", "novel", "nuclear", "numeric",
"nylon", "oasis", "object", "observe", "ocean", "octopus",
"olivia", "olympic", "omega", "opera", "optic", "optimal",
"orange", "orbit", "organic", "orient", "origin", "orlando",
"oscar", "oxford", "oxygen", "ozone", "pablo", "pacific",
"pagoda", "palace", "pamela", "panama", "panda", "panel",
"panic", "paradox", "pardon", "paris", "parker", "parking",
"parody", "partner", "passage", "passive", "pasta", "pastel",
"patent", "patriot", "patrol", "patron", "pegasus", "pelican",
"penguin", "pepper", "percent", "perfect", "perfume", "period",
"permit", "person", "peru", "phone", "photo", "piano",
"picasso", "picnic", "picture", "pigment", "pilgrim", "pilot",
"pirate", "pixel", "pizza", "planet", "plasma", "plaster",
"plastic", "plaza", "pocket", "poem", "poetic", "poker",
"polaris", "police", "politic", "polo", "polygon", "pony",
"popcorn", "popular", "postage", "postal", "precise", "prefix",
"premium", "present", "price", "prince", "printer", "prism",
"private", "product", "profile", "program", "project", "protect",
"proton", "public", "pulse", "puma", "pyramid", "queen",
"radar", "radio", "random", "rapid", "rebel", "record",
"recycle", "reflex", "reform", "regard", "regular", "relax",
"report", "reptile", "reverse", "ricardo", "ringo", "ritual",
"robert", "robot", "rocket", "rodeo", "romeo", "royal",
"russian", "safari", "salad", "salami", "salmon", "salon",
"salute", "samba", "sandra", "santana", "sardine", "school",
"screen", "script", "second", "secret", "section", "segment",
"select", "seminar", "senator", "senior", "sensor", "serial",
"service", "sheriff", "shock", "sierra", "signal", "silicon",
"silver", "similar", "simon", "single", "siren", "slogan",
"social", "soda", "solar", "solid", "solo", "sonic",
"soviet", "special", "speed", "spiral", "spirit", "sport",
"static", "station", "status", "stereo", "stone", "stop",
"street", "strong", "student", "studio", "style", "subject",
"sultan", "super", "susan", "sushi", "suzuki", "switch",
"symbol", "system", "tactic", "tahiti", "talent", "tango",
"tarzan", "taxi", "telex", "tempo", "tennis", "texas",
"textile", "theory", "thermos", "tiger", "titanic", "tokyo",
"tomato", "topic", "tornado", "toronto", "torpedo", "total",
"totem", "tourist", "tractor", "traffic", "transit", "trapeze",
"travel", "tribal", "trick", "trident", "trilogy", "tripod",
"tropic", "trumpet", "tulip", "tuna", "turbo", "twist",
"ultra", "uniform", "union", "uranium", "vacuum", "valid",
"vampire", "vanilla", "vatican", "velvet", "ventura", "venus",
"vertigo", "veteran", "victor", "video", "vienna", "viking",
"village", "vincent", "violet", "violin", "virtual", "virus",
"visa", "vision", "visitor", "visual", "vitamin", "viva",
"vocal", "vodka", "volcano", "voltage", "volume", "voyage",
"water", "weekend", "welcome", "western", "window", "winter",
"wizard", "wolf", "world", "xray", "yankee", "yoga",
"yogurt", "yoyo", "zebra", "zero", "zigzag", "zipper",
"zodiac", "zoom", "abraham", "action", "address", "alabama",
"alfred", "almond", "ammonia", "analyze", "annual", "answer",
"apple", "arena", "armada", "arsenal", "atlanta", "atomic",
"avenue", "average", "bagel", "baker", "ballet", "bambino",
"bamboo", "barbara", "basket", "bazaar", "benefit", "bicycle",
"bishop", "blitz", "bonjour", "bottle", "bridge", "british",
"brother", "brush", "budget", "cabaret", "cadet", "candle",
"capitan", "capsule", "career", "cartoon", "channel", "chapter",
"cheese", "circle", "cobalt", "cockpit", "college", "compass",
"comrade", "condor", "crimson", "cyclone", "darwin", "declare",
"degree", "delete", "delphi", "denver", "desert", "divide",
"dolby", "domain", "domingo", "double", "drink", "driver",
"eagle", "earth", "echo", "eclipse", "editor", "educate",
"edward", "effect", "electra", "emerald", "emotion", "empire",
"empty", "escape", "eternal", "evening", "exhibit", "expand",
"explore", "extreme", "ferrari", "first", "flag", "folio",
"forget", "forward", "freedom", "fresh", "friday", "fuji",
"galileo", "garcia", "genesis", "gold", "gravity", "habitat",
"hamlet", "harlem", "helium", "holiday", "house", "hunter",
"ibiza", "iceberg", "imagine", "infant", "isotope", "jackson",
"jamaica", "jasmine", "java", "jessica", "judo", "kitchen",
"lazarus", "letter", "license", "lithium", "loyal", "lucky",
"magenta", "mailbox", "manual", "marble", "mary", "maxwell",
"mayor", "milk", "monarch", "monday", "money", "morning",
"mother", "mystery", "native", "nectar", "nelson", "network",
"next", "nikita", "nobel", "nobody", "nominal", "norway",
"nothing", "number", "october", "office", "oliver", "opinion",
"option", "order", "outside", "package", "pancake", "pandora",
"panther", "papa", "patient", "pattern", "pedro", "pencil",
"people", "phantom", "philips", "pioneer", "pluto", "podium",
"portal", "potato", "prize", "process", "protein", "proxy",
"pump", "pupil", "python", "quality", "quarter", "quiet",
"rabbit", "radical", "radius", "rainbow", "ralph", "ramirez",
"ravioli", "raymond", "respect", "respond", "result", "resume",
"retro", "richard", "right", "risk", "river", "roger",
"roman", "rondo", "sabrina", "salary", "salsa", "sample",
"samuel", "saturn", "savage", "scarlet", "scoop", "scorpio",
"scratch", "scroll", "sector", "serpent", "shadow", "shampoo",
"sharon", "sharp", "short", "shrink", "silence", "silk",
"simple", "slang", "smart", "smoke", "snake", "society",
"sonar", "sonata", "soprano", "source", "sparta", "sphere",
"spider", "sponsor", "spring", "acid", "adios", "agatha",
"alamo", "alert", "almanac", "aloha", "andrea", "anita",
"arcade", "aurora", "avalon", "baby", "baggage", "balloon",
"bank", "basil", "begin", "biscuit", "blue", "bombay",
"brain", "brenda", "brigade", "cable", "carmen", "cello",
"celtic", "chariot", "chrome", "citrus", "civil", "cloud",
"common", "compare", "cool", "copper", "coral", "crater",
"cubic", "cupid", "cycle", "depend", "door", "dream",
"dynasty", "edison", "edition", "enigma", "equal", "eric",
"event", "evita", "exodus", "extend", "famous", "farmer",
"food", "fossil", "frog", "fruit", "geneva", "gentle",
"george", "giant", "gilbert", "gossip", "gram", "greek",
"grille", "hammer", "harvest", "hazard", "heaven", "herbert",
"heroic", "hexagon", "husband", "immune", "inca", "inch",
"initial", "isabel", "ivory", "jason", "jerome", "joel",
"joshua", "journal", "judge", "juliet", "jump", "justice",
"kimono", "kinetic", "leonid", "lima", "maze", "medusa",
"member", "memphis", "michael", "miguel", "milan", "mile",
"miller", "mimic", "mimosa", "mission", "monkey", "moral",
"moses", "mouse", "nancy", "natasha", "nebula", "nickel",
"nina", "noise", "orchid", "oregano", "origami", "orinoco",
"orion", "othello", "paper", "paprika", "prelude", "prepare",
"pretend", "profit", "promise", "provide", "puzzle", "remote",
"repair", "reply", "rival", "riviera", "robin", "rose",
"rover", "rudolf", "saga", "sahara", "scholar", "shelter",
"ship", "shoe", "sigma", "sister", "sleep", "smile",
"spain", "spark", "split", "spray", "square", "stadium",
"star", "storm", "story", "strange", "stretch", "stuart",
"subway", "sugar", "sulfur", "summer", "survive", "sweet",
"swim", "table", "taboo", "target", "teacher", "telecom",
"temple", "tibet", "ticket", "tina", "today", "toga",
"tommy", "tower", "trivial", "tunnel", "turtle", "twin",
"uncle", "unicorn", "unique", "update", "valery", "vega",
"version", "voodoo", "warning", "william", "wonder", "year",
"yellow", "young", "absent", "absorb", "accent", "alfonso",
"alias", "ambient", "andy", "anvil", "appear", "apropos",
"archer", "ariel", "armor", "arrow", "austin", "avatar",
"axis", "baboon", "bahama", "bali", "balsa", "bazooka",
"beach", "beast", "beatles", "beauty", "before", "benny",
"betty", "between", "beyond", "billy", "bison", "blast",
"bless", "bogart", "bonanza", "book", "border", "brave",
"bread", "break", "broken", "bucket", "buenos", "buffalo",
"bundle", "button", "buzzer", "byte", "caesar", "camilla",
"canary", "candid", "carrot", "cave", "chant", "child",
"choice", "chris", "cipher", "clarion", "clark", "clever",
"cliff", "clone", "conan", "conduct", "congo", "content",
"costume", "cotton", "cover", "crack", "current", "danube",
"data", "decide", "desire", "detail", "dexter", "dinner",
"dispute", "donor", "druid", "drum", "easy", "eddie",
"enjoy", "enrico", "epoxy", "erosion", "except", "exile",
"explain", "fame", "fast", "father", "felix", "field",
"fiona", "fire", "fish", "flame", "flex", "flipper",
"float", "flood", "floor", "forbid", "forever", "fractal",
"frame", "freddie", "front", "fuel", "gallop", "game",
"garbo", "gate", "gibson", "ginger", "giraffe", "gizmo",
"glass", "goblin", "gopher", "grace", "gray", "gregory",
"grid", "griffin", "ground", "guest", "gustav", "gyro",
"hair", "halt", "harris", "heart", "heavy", "herman",
"hippie", "hobby", "honey", "hope", "horse", "hostel",
"hydro", "imitate", "info", "ingrid", "inside", "invent",
"invest", "invite", "iron", "ivan", "james", "jester",
"jimmy", "join", "joseph", "juice", "julius", "july",
"justin", "kansas", "karl", "kevin", "kiwi", "ladder",
"lake", "laura", "learn", "legacy", "legend", "lesson",
"life", "light", "list", "locate", "lopez", "lorenzo",
"love", "lunch", "malta", "mammal", "margo", "marion",
"mask", "match", "mayday", "meaning", "mercy", "middle",
"mike", "mirror", "modest", "morph", "morris", "nadia",
"nato", "navy", "needle", "neuron", "never", "newton",
"nice", "night", "nissan", "nitro", "nixon", "north",
"oberon", "octavia", "ohio", "olga", "open", "opus",
"orca", "oval", "owner", "page", "paint", "palma",
"parade", "parent", "parole", "paul", "peace", "pearl",
"perform", "phoenix", "phrase", "pierre", "pinball", "place",
"plate", "plato", "plume", "pogo", "point", "polite",
"polka", "poncho", "powder", "prague", "press", "presto",
"pretty", "prime", "promo", "quasi", "quest", "quick",
"quiz", "quota", "race", "rachel", "raja", "ranger",
"region", "remark", "rent", "reward", "rhino", "ribbon",
"rider", "road", "rodent", "round", "rubber", "ruby",
"rufus", "sabine", "saddle", "sailor", "saint", "salt",
"satire", "scale", "scuba", "season", "secure", "shake",
"shallow", "shannon", "shave", "shelf", "sherman", "shine",
"shirt", "side", "sinatra", "sincere", "size", "slalom",
"slow", "small", "snow", "sofia", "song", "sound",
"south", "speech", "spell", "spend", "spoon", "stage",
"stamp", "stand", "state", "stella", "stick", "sting",
"stock", "store", "sunday", "sunset", "support", "sweden",
"swing", "tape", "think", "thomas", "tictac", "time",
"toast", "tobacco", "tonight", "torch", "torso", "touch",
"toyota", "trade", "tribune", "trinity", "triton", "truck",
"trust", "type", "under", "unit", "urban", "urgent",
"user", "value", "vendor", "venice", "verona", "vibrate",
"virgo", "visible", "vista", "vital", "voice", "vortex",
"waiter", "watch", "wave", "weather", "wedding", "wheel",
"whiskey", "wisdom", "deal", "null", "nurse", "quebec",
"reserve", "reunion", "roof", "singer", "verbal", "amen",
"ego", "fax", "jet", "job", "rio", "ski",
"yes",
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

9
src/tcp/defaults.go Normal file
View File

@ -0,0 +1,9 @@
package tcp
import "time"
const (
DEFAULT_LOG_LEVEL = "debug"
DEFAULT_ROOM_CLEANUP_INTERVAL = 10 * time.Minute
DEFAULT_ROOM_TTL = 3 * time.Hour
)

53
src/tcp/options.go Normal file
View File

@ -0,0 +1,53 @@
package tcp
import (
"fmt"
"time"
)
// TODO: maybe export from logger library?
var availableLogLevels = []string{"info", "error", "warn", "debug", "trace"}
type serverOptsFunc func(s *server) error
func WithBanner(banner ...string) serverOptsFunc {
return func(s *server) error {
if len(banner) > 0 {
s.banner = banner[0]
}
return nil
}
}
func WithLogLevel(level string) serverOptsFunc {
return func(s *server) error {
if !containsSlice(availableLogLevels, level) {
return fmt.Errorf("invalid log level specified: %s", level)
}
s.debugLevel = level
return nil
}
}
func WithRoomCleanupInterval(interval time.Duration) serverOptsFunc {
return func(s *server) error {
s.roomCleanupInterval = interval
return nil
}
}
func WithRoomTTL(ttl time.Duration) serverOptsFunc {
return func(s *server) error {
s.roomTTL = ttl
return nil
}
}
func containsSlice(s []string, e string) bool {
for _, ss := range s {
if e == ss {
return true
}
}
return false
}

View File

@ -23,6 +23,11 @@ type server struct {
banner string
password string
rooms roomMap
roomCleanupInterval time.Duration
roomTTL time.Duration
stopRoomCleanup chan struct{}
}
type roomInfo struct {
@ -39,46 +44,55 @@ type roomMap struct {
const pingRoom = "pinglkasjdlfjsaldjf"
var timeToRoomDeletion = 10 * time.Minute
// Run starts a tcp listener, run async
func Run(debugLevel, host, port, password string, banner ...string) (err error) {
// newDefaultServer initializes a new server, with some default configuration options
func newDefaultServer() *server {
s := new(server)
s.roomCleanupInterval = DEFAULT_ROOM_CLEANUP_INTERVAL
s.roomTTL = DEFAULT_ROOM_TTL
s.debugLevel = DEFAULT_LOG_LEVEL
s.stopRoomCleanup = make(chan struct{})
return s
}
// RunWithOptionsAsync asynchronously starts a TCP listener.
func RunWithOptionsAsync(host, port, password string, opts ...serverOptsFunc) error {
s := newDefaultServer()
s.host = host
s.port = port
s.password = password
s.debugLevel = debugLevel
if len(banner) > 0 {
s.banner = banner[0]
for _, opt := range opts {
err := opt(s)
if err != nil {
return fmt.Errorf("could not apply optional configurations: %w", err)
}
}
return s.start()
}
// Run starts a tcp listener, run async
func Run(debugLevel, host, port, password string, banner ...string) (err error) {
return RunWithOptionsAsync(host, port, password, WithBanner(banner...), WithLogLevel(debugLevel))
}
func (s *server) start() (err error) {
log.SetLevel(s.debugLevel)
log.Debugf("starting with password '%s'", s.password)
// Mask our password in logs
maskedPassword := ""
if len(s.password) > 2 {
maskedPassword = fmt.Sprintf("%c***%c", s.password[0], s.password[len(s.password)-1])
} else {
maskedPassword = s.password
}
log.Debugf("starting with password '%s'", maskedPassword)
s.rooms.Lock()
s.rooms.rooms = make(map[string]roomInfo)
s.rooms.Unlock()
// delete old rooms
go func() {
for {
time.Sleep(timeToRoomDeletion)
var roomsToDelete []string
s.rooms.Lock()
for room := range s.rooms.rooms {
if time.Since(s.rooms.rooms[room].opened) > 3*time.Hour {
roomsToDelete = append(roomsToDelete, room)
}
}
s.rooms.Unlock()
for _, room := range roomsToDelete {
s.deleteRoom(room)
}
}
}()
go s.deleteOldRooms()
defer s.stopRoomDeletion()
err = s.run()
if err != nil {
@ -173,6 +187,39 @@ func (s *server) run() (err error) {
}
}
// deleteOldRooms checks for rooms at a regular interval and removes those that
// have exceeded their allocated TTL.
func (s *server) deleteOldRooms() {
ticker := time.NewTicker(s.roomCleanupInterval)
for {
select {
case <-ticker.C:
var roomsToDelete []string
s.rooms.Lock()
for room := range s.rooms.rooms {
if time.Since(s.rooms.rooms[room].opened) > s.roomTTL {
roomsToDelete = append(roomsToDelete, room)
}
}
s.rooms.Unlock()
for _, room := range roomsToDelete {
s.deleteRoom(room)
log.Debugf("room cleaned up: %s", room)
}
case <-s.stopRoomCleanup:
ticker.Stop()
log.Debug("room cleanup stopped")
return
}
}
}
func (s *server) stopRoomDeletion() {
log.Debug("stop room cleanup fired")
s.stopRoomCleanup <- struct{}{}
}
var weakKey = []byte{1, 2, 3}
func (s *server) clientCommunication(port string, c *comm.Comm) (room string, err error) {

View File

@ -23,8 +23,8 @@ func BenchmarkConnection(b *testing.B) {
func TestTCP(t *testing.T) {
log.SetLevel("error")
timeToRoomDeletion = 100 * time.Millisecond
go Run("debug", "127.0.0.1", "8381", "pass123", "8382")
timeToRoomDeletion := 100 * time.Millisecond
go RunWithOptionsAsync("127.0.0.1", "8381", "pass123", WithBanner("8382"), WithLogLevel("debug"), WithRoomTTL(timeToRoomDeletion))
time.Sleep(timeToRoomDeletion)
err := PingServer("127.0.0.1:8381")
assert.Nil(t, err)

View File

@ -11,7 +11,6 @@ import (
"encoding/hex"
"fmt"
"io"
"log"
"math"
"math/big"
"net"
@ -26,7 +25,8 @@ import (
"github.com/cespare/xxhash"
"github.com/kalafut/imohash"
"github.com/minio/highwayhash"
"github.com/schollz/mnemonicode"
"github.com/schollz/croc/v10/src/mnemonicode"
log "github.com/schollz/logger"
"github.com/schollz/progressbar/v3"
)
@ -246,19 +246,21 @@ func SHA256(s string) string {
// PublicIP returns public ip address
func PublicIP() (ip string, err error) {
resp, err := http.Get("https://canhazip.com")
// ask ipv4.icanhazip.com for the public ip
// by making http request
// if the request fails, return nothing
resp, err := http.Get("http://ipv4.icanhazip.com")
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
ip = strings.TrimSpace(string(bodyBytes))
}
// read the body of the response
// and return the ip address
buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body)
ip = strings.TrimSpace(buf.String())
return
}
@ -266,7 +268,8 @@ func PublicIP() (ip string, err error) {
func LocalIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
log.Error(err)
return ""
}
defer conn.Close()
@ -467,12 +470,12 @@ func IsLocalIP(ipaddress string) bool {
func ZipDirectory(destination string, source string) (err error) {
if _, err = os.Stat(destination); err == nil {
log.Fatalf("%s file already exists!\n", destination)
log.Errorf("%s file already exists!\n", destination)
}
fmt.Fprintf(os.Stderr, "Zipping %s to %s\n", source, destination)
file, err := os.Create(destination)
if err != nil {
log.Fatalln(err)
log.Error(err)
}
defer file.Close()
writer := zip.NewWriter(file)
@ -483,22 +486,22 @@ func ZipDirectory(destination string, source string) (err error) {
defer writer.Close()
err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Fatalln(err)
log.Error(err)
}
if info.Mode().IsRegular() {
f1, err := os.Open(path)
if err != nil {
log.Fatalln(err)
log.Error(err)
}
defer f1.Close()
zipPath := strings.ReplaceAll(path, source, strings.TrimSuffix(destination, ".zip"))
zipPath = filepath.ToSlash(zipPath)
w1, err := writer.Create(zipPath)
if err != nil {
log.Fatalln(err)
log.Error(err)
}
if _, err := io.Copy(w1, f1); err != nil {
log.Fatalln(err)
log.Error(err)
}
fmt.Fprintf(os.Stderr, "\r\033[2K")
fmt.Fprintf(os.Stderr, "\rAdding %s", zipPath)
@ -506,7 +509,7 @@ func ZipDirectory(destination string, source string) (err error) {
return nil
})
if err != nil {
log.Fatalln(err)
log.Error(err)
}
fmt.Fprintf(os.Stderr, "\n")
return nil
@ -515,7 +518,7 @@ func ZipDirectory(destination string, source string) (err error) {
func UnzipDirectory(destination string, source string) error {
archive, err := zip.OpenReader(source)
if err != nil {
log.Fatalln(err)
log.Error(err)
}
defer archive.Close()
@ -527,7 +530,7 @@ func UnzipDirectory(destination string, source string) error {
// make sure the filepath does not have ".."
filePath = filepath.Clean(filePath)
if strings.Contains(filePath, "..") {
log.Fatalf("Invalid file path %s\n", filePath)
log.Errorf("Invalid file path %s\n", filePath)
}
if f.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
@ -535,7 +538,7 @@ func UnzipDirectory(destination string, source string) error {
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
log.Fatalln(err)
log.Error(err)
}
// check if file exists
@ -550,16 +553,16 @@ func UnzipDirectory(destination string, source string) error {
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
log.Fatalln(err)
log.Error(err)
}
fileInArchive, err := f.Open()
if err != nil {
log.Fatalln(err)
log.Error(err)
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
log.Fatalln(err)
log.Error(err)
}
dstFile.Close()
@ -572,15 +575,63 @@ func UnzipDirectory(destination string, source string) error {
// ValidFileName checks if a filename is valid
// by making sure it has no invisible characters
func ValidFileName(fname string) (err error) {
// make sure it doesn't contain unicode or invisible characters
for _, r := range fname {
if !unicode.IsGraphic(r) {
err = fmt.Errorf("non-graphical unicode: %x U+%d in '%s'", string(r), r, fname)
err = fmt.Errorf("non-graphical unicode: %x U+%d in '%x'", string(r), r, fname)
return
}
if !unicode.IsPrint(r) {
err = fmt.Errorf("non-printable unicode: %x U+%d in '%s'", string(r), r, fname)
err = fmt.Errorf("non-printable unicode: %x U+%d in '%x'", string(r), r, fname)
return
}
}
// make sure basename does not include ".." or path separators
_, basename := filepath.Split(fname)
if strings.Contains(basename, "..") {
err = fmt.Errorf("basename cannot contain '..': '%s'", basename)
return
}
if strings.Contains(basename, string(os.PathSeparator)) {
err = fmt.Errorf("basename cannot contain path separators: '%s'", basename)
return
}
// make sure the filename is not an absolute path
if filepath.IsAbs(fname) {
err = fmt.Errorf("filename cannot be an absolute path: '%s'", fname)
return
}
return
}
const crocRemovalFile = "croc-marked-files.txt"
func MarkFileForRemoval(fname string) {
// append the fname to the list of files to remove
f, err := os.OpenFile(crocRemovalFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o600)
if err != nil {
log.Debug(err)
return
}
defer f.Close()
_, err = f.WriteString(fname + "\n")
}
func RemoveMarkedFiles() (err error) {
// read the file and remove all the files
f, err := os.Open(crocRemovalFile)
if err != nil {
return
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fname := scanner.Text()
err = os.Remove(fname)
if err == nil {
log.Tracef("Removed %s", fname)
}
}
os.Remove(crocRemovalFile)
return
}

View File

@ -6,6 +6,7 @@ import (
"log"
"math/rand"
"os"
"path"
"strings"
"testing"
@ -260,5 +261,7 @@ func TestValidFileName(t *testing.T) {
// contains invisible character
err := ValidFileName("D中文.cslouglas")
assert.NotNil(t, err)
assert.Equal(t, "non-graphical unicode: e2808b U+8203 in 'D中文.cslouglas'", err.Error())
assert.Equal(t, "non-graphical unicode: e2808b U+8203 in '44e4b8ade696872e63736c6f75676c6173e2808b'", err.Error())
assert.NotNil(t, ValidFileName("hi..txt"))
assert.NotNil(t, ValidFileName(path.Join(string(os.PathSeparator), "abs", string(os.PathSeparator), "hi.txt")))
}