Compare commits

..

1430 Commits
v4.0.4 ... main

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
Zack Scholl 4c120c4963 bump version 2024-06-26 10:55:12 -07:00
Zack 7c3dc4453a croc checks for error in file name 2024-06-26 06:58:12 -07:00
Zack 3e804a4a09 ValidFileName returns error 2024-06-26 06:57:57 -07:00
Zack 907f2b3824 Merge branch 'main' of github.com:schollz/croc 2024-06-26 06:09:33 -07:00
Zack 05da5007ed add new test 2024-06-26 06:09:23 -07:00
Zack 791e4c22d2
Merge pull request #742 from ryancdotorg/main
correct classic mode prompt
2024-06-22 08:26:12 -07:00
Zack dd3e3ff1ab
Merge pull request #740 from schollz/dependabot/github_actions/docker/build-push-action-6
build(deps): bump docker/build-push-action from 5 to 6
2024-06-22 08:25:17 -07:00
Ryan Castellucci 44f2b94164 correct classic mode prompt
"Do you wish to continue to enable the classic mode?" actually defaults to "no" rather than "yes" as the prompt text implies, this corrects the prompt text.
2024-06-22 09:03:42 +01:00
dependabot[bot] 6c7120edbb
build(deps): bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-18 09:03:31 +00:00
Zack 1e34537bb2
Merge pull request #737 from schollz:schollz/issue735
fix: croc hangs with broken dns
2024-06-13 08:28:06 -07:00
Zack 0d0effd983 fix: croc hangs with broken dns
Fixes #735
2024-06-13 08:27:55 -07:00
Zack e85575f3a5
Merge pull request #734 from schollz/dependabot/go_modules/github.com/schollz/progressbar/v3-3.14.4
build(deps): bump github.com/schollz/progressbar/v3 from 3.14.3 to 3.14.4
2024-06-10 05:57:51 -07:00
dependabot[bot] 0afdcd7005
build(deps): bump github.com/schollz/progressbar/v3
Bumps [github.com/schollz/progressbar/v3](https://github.com/schollz/progressbar) from 3.14.3 to 3.14.4.
- [Release notes](https://github.com/schollz/progressbar/releases)
- [Commits](https://github.com/schollz/progressbar/compare/v3.14.3...v3.14.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 08:21:44 +00:00
Zack ca8f011844 v10.0.8 2024-06-06 10:22:46 -07:00
Zack 55518176e1 Merge branch 'main' of github.com:schollz/croc 2024-06-06 10:21:42 -07:00
Zack e502cf0c82 update dependencies 2024-06-06 10:19:44 -07:00
Zack 5cf4d7c103 update: imohash samples more of the file 2024-06-06 10:19:23 -07:00
Zack c28c4786a1
Merge pull request #728 from schollz/dependabot/go_modules/golang.org/x/net-0.26.0
build(deps): bump golang.org/x/net from 0.25.0 to 0.26.0
2024-06-05 19:53:49 -07:00
Zack 6f974d96e8
Merge pull request #732 from raimocom/main
Update croc.go - console output clarification
2024-06-05 18:48:24 -07:00
raimocom c2cb15cb73
Update croc.go - console output clarification 2024-06-06 03:43:01 +02:00
Zack 2d648aa580
Merge pull request #731 from raimocom/main
Update cli.go (help output clarification)
2024-06-05 18:42:00 -07:00
raimocom 80074b3727
Update cli.go (help clarification overwrite/resume) 2024-06-06 03:38:15 +02:00
raimocom e47ca8fbcb
Update cli.go 2024-06-06 02:56:53 +02:00
dependabot[bot] d011290559
build(deps): bump golang.org/x/net from 0.25.0 to 0.26.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.25.0 to 0.26.0.
- [Commits](https://github.com/golang/net/compare/v0.25.0...v0.26.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-05 08:46:37 +00:00
Zack 50e0f625bc v10.0.7 2024-05-31 14:32:59 -07:00
Zack 94af2374c3 Merge branch 'main' of github.com:schollz/croc 2024-05-31 14:32:03 -07:00
Zack a4322faa25 ui: add newlines to skipping messages 2024-05-31 14:31:46 -07:00
Zack 23dce2aa3e
Merge pull request #724 from schollz:schollz/issue723
fix: receiver needs to exit without initializing files if no files being transfered
2024-05-31 11:45:51 -07:00
Zack 88002b322d fix: receiver needs to exit without initializing files if no files being transfered 2024-05-31 11:44:56 -07:00
Zack 9246408278 for valid filename tests 2024-05-30 15:21:51 -07:00
Zack fbf1eeedce v10.0.6 2024-05-28 16:24:29 -07:00
Zack e4c9f2d9fb
Merge pull request #721 from schollz:schollz/issue720
show hash progress on large files
2024-05-28 16:21:45 -07:00
Zack c0c3370d9b add highway hash 2024-05-28 16:19:38 -07:00
Zack f6bd13fa06 show hash progress on large files 2024-05-28 16:08:31 -07:00
Zack Scholl f83616e9bd readme: remove coverage badge 2024-05-26 11:37:03 -07:00
Zack Scholl 23f385ab2f readme: update badge for CI 2024-05-26 11:35:54 -07:00
Zack Scholl 78feb393de fix println warnings 2024-05-26 11:33:21 -07:00
Zack 69fc3cee47 v10.0.5 2024-05-26 07:58:08 -07:00
Zack a5da77cf49
Merge pull request #717 from schollz:schollz/issue716
new: add flag `--classic` with warning for passing shared secret on single-user systems
2024-05-26 07:55:31 -07:00
Zack f66e17dd46 add the checks for the classic insecure mode 2024-05-26 07:54:37 -07:00
Zack 63c9201938 new: add flag with warning for passing shared secret on single-user systems 2024-05-26 07:52:12 -07:00
Zack ca7a5979cc need environmental variable on all unix systems 2024-05-26 07:20:48 -07:00
Zack fc457557e0 v10.0.4 2024-05-25 09:02:34 -07:00
Zack f044f4dd86
Merge pull request #713 from schollz:schollz/issue712
escape filenames that have invisible characters while allowing other languages
2024-05-25 09:00:36 -07:00
Zack a2e71c7e1a escape filenames that have invisible characters while allowing other languages
Fixes #712
2024-05-25 08:59:38 -07:00
Zack dff34fa7fc fix comment 2024-05-24 19:44:28 -07:00
Zack Scholl 08103bb7bb v10.0.3 2024-05-24 18:04:29 -07:00
Zack Scholl 4091ef0496 fix: remove hash extra 2024-05-24 18:03:51 -07:00
Zack 381f8369a3 update bug report 2024-05-23 09:49:18 -07:00
Zack a95d67e31c v10.0.2 2024-05-23 09:47:15 -07:00
Zack b0920bbe70
Merge pull request #708 from schollz/fix10
fix message passing for initial secure layer
2024-05-23 09:46:40 -07:00
Zack ed55c746c2 fix message passing for initial secure layer 2024-05-23 09:44:34 -07:00
Zack 8e10eac5c5 fix 2024-05-23 09:34:17 -07:00
Zack 43f1c53538 v10.0.1 2024-05-23 08:35:56 -07:00
Zack 3acac5d53b
Merge pull request #707 from schollz:schollz/issue706
ux: improve the environmental variable messaging for sending/receiving
2024-05-23 08:34:52 -07:00
Zack 66f0d1264a improve the ux around sending 2024-05-23 08:33:00 -07:00
Zack ee713c5146 improve ux around receiving 2024-05-23 08:27:52 -07:00
Zack 6181903c83 go.mod v9 -> v10 2024-05-23 06:25:53 -07:00
Zack 7acd2def69 version bump for breaking change 2024-05-23 06:15:03 -07:00
Zack eb0909033e reduce description lengths 2024-05-22 10:10:55 -07:00
Zack f6d862eac0 bump version 2024-05-20 12:08:57 -07:00
Zack 5a6005f1eb bump version 2024-05-20 12:08:45 -07:00
Zack f6633cbac9
Merge pull request #702 from schollz:schollz/issue599
chore: improve efficiency and remove extraneous reads
2024-05-20 10:39:49 -07:00
Zack d8ef7cda20 chore: improve efficiency and remove extraneous reads 2024-05-20 10:39:22 -07:00
Zack 7622e636e4 fix: refactor gathering ips 2024-05-20 10:16:37 -07:00
Zack bb018fd725 fix: address shared secret before creatgin 2024-05-20 10:16:02 -07:00
Zack 863dabb93a
Merge pull request #701 from schollz/issue598
fix: shared secret should be read from environmental variable
2024-05-20 09:53:39 -07:00
Zack 6f5f16aa1c
Merge pull request #700 from schollz/issue597
fix: establish encryption layer before transfering ip information
2024-05-20 09:53:31 -07:00
Zack 0f1ca436cd
Merge pull request #699 from schollz/issue596
fix: use more secure shared secret as room name
2024-05-20 09:53:17 -07:00
Zack 4929635eb8
Merge pull request #698 from schollz/schollz/issue594
fix: prompt for overwriting when unzipping
2024-05-20 09:53:09 -07:00
Zack 3f12f75fae
Merge pull request #697 from schollz/issue593
fix: client quits when discovering dangerous paths
2024-05-20 09:52:58 -07:00
Zack e255d472a6 fix: shared secret should be read from environmental variable 2024-05-20 09:46:38 -07:00
Zack 2ffd4daeaf fix: establish encryption layer before transfering ip information 2024-05-20 09:37:42 -07:00
Zack accb310337 ignore 2024-05-20 09:11:08 -07:00
Zack 2b4c088100 fix: use more secure shared secret as room name 2024-05-20 09:08:10 -07:00
Zack a591833dbf fix: filter escape sequences in filenames 2024-05-20 08:38:36 -07:00
Zack b3668a6f5c fix: prompt for overwriting when unzipping 2024-05-20 08:31:47 -07:00
Zack b05c3c8c42 fix: client quits when discovering dangerous paths 2024-05-20 08:23:21 -07:00
Zack 13bc190f8b ignore big file 2024-05-20 08:08:38 -07:00
Zack 1b90484bb8 chore: update dependencies 2024-05-20 06:08:20 -07:00
Zack Scholl 05359d6976 update deps 2024-05-12 16:15:52 +00:00
Zack Scholl cc4d74c490 Merge branch 'main' of github.com:schollz/croc 2024-04-06 16:45:03 +00:00
Zack d81116382f bump version to 9.6.15 2024-04-06 09:44:08 -07:00
Zack Scholl 94cc880568 Merge branch 'main' of github.com:schollz/croc 2024-04-06 16:44:02 +00:00
Zack 24b907f4bb chore: update deps 2024-04-06 09:43:27 -07:00
Zack Scholl 8166b2dbed Merge branch 'main' of github.com:schollz/croc 2024-04-05 21:39:02 +00:00
Zack 14187f6f30
Merge pull request #688 from schollz/dependabot/go_modules/golang.org/x/crypto-0.22.0
Bump golang.org/x/crypto from 0.21.0 to 0.22.0
2024-04-05 14:38:56 -07:00
dependabot[bot] 90682d3ebd
Bump golang.org/x/crypto from 0.21.0 to 0.22.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.21.0 to 0.22.0.
- [Commits](https://github.com/golang/crypto/compare/v0.21.0...v0.22.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-05 08:21:46 +00:00
Zack Scholl f4057aa28b Merge branch 'main' of github.com:schollz/croc 2024-04-04 18:31:02 +00:00
Zack 3c2548aa69
Merge pull request #687 from schollz/dependabot/go_modules/golang.org/x/net-0.23.0
Bump golang.org/x/net from 0.22.0 to 0.23.0
2024-04-04 11:30:06 -07:00
dependabot[bot] 7bab9c3cb5
Bump golang.org/x/net from 0.22.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.22.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.22.0...v0.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-04 08:06:47 +00:00
Zack Scholl 355628f895 Merge branch 'main' of github.com:schollz/croc 2024-04-01 19:29:03 +00:00
Zack eaffc6dcac
Merge pull request #686 from a1lu/readonly
Avoid to create config dir if not required
2024-04-01 12:28:36 -07:00
a1lu 4baec420c8 Aovoid to create config dir if not required
If `--remember` is not set, the config dir should not created.
2024-04-01 13:39:04 +02:00
a1lu cd89e8043f Introduce var doRemember in cli receive function 2024-04-01 13:15:50 +02:00
Zack Scholl 1324ff8897 Merge branch 'main' of github.com:schollz/croc 2024-03-31 19:11:02 +00:00
Zack 8bc7a62b9e
Merge pull request #683 from a1lu/patch-1
Support spaces in 4 word codes
2024-03-31 12:10:32 -07:00
Zack Scholl 0c49ac3f02 Merge branch 'main' of github.com:schollz/croc 2024-03-31 19:09:02 +00:00
Zack 8b4ab4c86c
Merge pull request #685 from a1lu/config_files
Gracefully handle non existend receive config file
2024-03-31 12:08:50 -07:00
Zack Scholl f8f69e3157 Merge branch 'main' of github.com:schollz/croc 2024-03-31 19:08:03 +00:00
Zack 4e75e131c4
Merge pull request #682 from vihu/rg/update-error-message
Update error message to be more verbose
2024-03-31 12:07:45 -07:00
a1lu e599e56415 Gracefully handle non existend receive config file
If croc shall not remember the config, it should not exit if the config
file could not be opened. This is similar to the handling of the send
config.
2024-03-31 00:08:12 +01:00
a1lu 956598c427 Check $HOME as last 2024-03-30 23:24:52 +01:00
a1lu 618ae1e5d0
Support spaces in 4 word codes
Since the code was extended by the 4 digit block, the patch from https://github.com/schollz/croc/pull/198 did not work anymore.
2024-03-30 22:58:16 +01:00
Zack Scholl 7763a971f2 Merge branch 'main' of github.com:schollz/croc 2024-03-30 18:49:02 +00:00
Zack d2b7c80369 chore: update dependencies 2024-03-30 11:48:03 -07:00
Rahul Garg 241176d8a4
Update error message to be more verbose
Summary
----
This changes the error message (when connecting to an unavailble
channel) like so:

before:

```
$ croc 6764-jimmy-hilton-inside
securing channel...2024/03/28 17:16:25 room not ready
```

after:

```
$ ./croc 6764-jimmy-hilton-inside
securing channel...2024/03/28 17:16:12 room (secure channel) not ready, maybe peer disconnected
```
2024-03-28 17:16:01 -06:00
Zack Scholl 719f9b62c9 Merge branch 'main' of github.com:schollz/croc 2024-03-11 22:51:03 +00:00
Zack Scholl 483c5255bb chore: bump version to 9.6.14 2024-03-11 15:50:04 -07:00
Zack Scholl 03e6dcd220 Merge branch 'main' of github.com:schollz/croc 2024-03-11 22:50:02 +00:00
Zack Scholl 22ddbd83c2 chore: update deps 2024-03-11 15:49:09 -07:00
Zack Scholl 6b930c365b Merge branch 'main' of github.com:schollz/croc 2024-03-11 22:49:03 +00:00
Zack 1f6851f33b
Merge pull request #680 from schollz/dependabot/github_actions/softprops/action-gh-release-2
Bump softprops/action-gh-release from 1 to 2
2024-03-11 15:48:20 -07:00
Zack 61224b4e6b
Merge pull request #678 from schollz/dependabot/go_modules/github.com/stretchr/testify-1.9.0
Bump github.com/stretchr/testify from 1.8.2 to 1.9.0
2024-03-11 15:48:07 -07:00
Zack Scholl 6f2771e7b5 Merge branch 'main' of github.com:schollz/croc 2024-03-11 13:46:03 +00:00
Zack c21beccb7a
Merge pull request #679 from bitraid/fix-win-build
Fix Windows builds
2024-03-11 06:45:41 -07:00
dependabot[bot] 40f5e9ca1e
Bump softprops/action-gh-release from 1 to 2
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)

---
updated-dependencies:
- dependency-name: softprops/action-gh-release
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 08:56:10 +00:00
bitraid ed8c0475bf
Fix Windows builds 2024-03-09 22:31:27 +02:00
dependabot[bot] d7d7d3c8dc
Bump github.com/stretchr/testify from 1.8.2 to 1.9.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.9.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-05 04:57:38 +00:00
Zack Scholl 945ac74690 Merge branch 'main' of github.com:schollz/croc 2024-03-05 04:57:05 +00:00
Zack Scholl fff6f48001 chore: update dependencies 2024-03-04 20:56:40 -08:00
Zack Scholl 28ef8e99ac Merge branch 'main' of github.com:schollz/croc 2024-02-22 22:41:05 +00:00
Zack 28bb36b321 bump version 2024-02-22 14:40:20 -08:00
Zack Scholl ab2cb477a8 Merge branch 'main' of github.com:schollz/croc 2024-02-22 22:40:05 +00:00
Zack abc5029fce update release with LICENSE 2024-02-22 14:39:57 -08:00
Zack e7f67ebea7 update date 2024-02-22 14:39:50 -08:00
Zack Scholl c7f0228786 Merge branch 'main' of github.com:schollz/croc 2024-02-22 22:35:05 +00:00
Zack 741714504a
Merge pull request #671 from dbohdan/main
Build release binaries for DragonFly/Free/Net/OpenBSD
2024-02-22 14:34:06 -08:00
D. Bohdan be8a6689ff build release bins for DragonFly/Free/Net/OpenBSD 2024-02-22 21:22:32 +00:00
Zack Scholl de9c54e57a Merge branch 'main' of github.com:schollz/croc 2024-02-20 15:59:03 +00:00
Zack 53fc9ebd99 bump version 2024-02-20 07:58:27 -08:00
Zack 4159ba7668 do static builds of croc
following https://github.com/golang/go/issues/26492#issuecomment-435462350
2024-02-20 07:57:49 -08:00
Zack Scholl 064f84ccd3 Merge branch 'main' of github.com:schollz/croc 2024-02-19 15:55:51 +00:00
Zack 8ac1e3a501 bump version 2024-02-19 07:47:23 -08:00
Zack 11bc4eecc6 update deps 2024-02-19 07:46:53 -08:00
Zack d92cff92b9 add arm/arm64 builds for windows fixes #664 2024-02-19 07:46:35 -08:00
Zack 00f12b5742
Merge pull request #663 from TravisRoad/main
remove unnecessary trailing newline character when stdout is enabled
2024-02-18 06:32:28 -08:00
Travis 4f1f57b1ba remove unnecessary trailing newline character when stdout is enabled 2024-02-18 10:17:35 +08:00
Zack a240a4b982
Merge pull request #657 from schollz/dependabot/github_actions/actions/stale-9
Bump actions/stale from 5 to 9
2024-02-17 10:29:47 -08:00
Zack 508e0be335
Merge pull request #662 from qk-santi/ports-and-transfers
define ports by amount, not individually - v2
2024-02-17 10:28:58 -08:00
qk-santi e1644401da version compatible basePort and transfers 2024-02-17 19:09:53 +01:00
qk-santi c83eb59963 Revert "define ports by amount, not individually"
This reverts commit 87152f8706.
2024-02-17 18:41:41 +01:00
Zack f874e30151 revert go version back to go.1.21 because of glibc errors 2024-02-16 06:56:33 -08:00
Zack b278f5a41d bump version 2024-02-16 06:56:06 -08:00
Zack ce91e3b420
Merge pull request #660 from qk-santi/ports-and-transfers
define ports by amount, not individually
2024-02-12 08:08:01 -07:00
Zack 30a6b14443
Merge pull request #659 from qk-santi/hide-relay-not-used
hide relay param if not going to be used
2024-02-12 06:37:28 -07:00
qk-santi 87152f8706 define ports by amount, not individually 2024-02-12 09:58:51 +01:00
qk-santi 48eb2a2a7c hide relay param if not going to be used 2024-02-12 09:30:20 +01:00
dependabot[bot] 816ad09a50
Bump actions/stale from 5 to 9
Bumps [actions/stale](https://github.com/actions/stale) from 5 to 9.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v5...v9)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 09:01:53 +00:00
Zack a2228e80c2
Create stale.yml 2024-02-08 13:43:05 -07:00
Zack Scholl 230de9184d bump version 2024-02-08 13:39:45 -07:00
Zack 3c781069ca
Merge pull request #653 from schollz/dependabot/go_modules/golang.org/x/crypto-0.19.0
Bump golang.org/x/crypto from 0.18.0 to 0.19.0
2024-02-08 13:38:12 -07:00
Zack 7274a8bd4b
Merge pull request #655 from schollz/schollz/issue650
add build for windows 7
2024-02-08 13:37:54 -07:00
Zack Scholl 3382306342 add build for windows 7 2024-02-08 13:37:10 -07:00
dependabot[bot] ad47739c8f
Bump golang.org/x/crypto from 0.18.0 to 0.19.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/crypto/compare/v0.18.0...v0.19.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-08 08:07:15 +00:00
Zack 2f33b14b3d
Merge pull request #581 from sitiom/patch-1
switch winget releaser runner to `ubuntu-latest`
2024-02-06 18:12:51 -08:00
Zack 4025efcd48 bump the default.txt 2024-02-06 15:58:18 -08:00
Zack f41a2afead bump version and fix installer 2024-02-06 15:51:07 -08:00
Zack ba75f7badb add release workflow for generating binaries 2024-02-06 15:37:28 -08:00
Zack 55c954117a update deps 2024-02-06 14:33:01 -08:00
Zack 4d083f8d10
Merge pull request #646 from rehanone/fix-docker-deplyment
Fix for the failing CD build
2024-02-06 08:05:08 -08:00
Rehan Mahmood 9ad2af18bd Added the `gcc` and `musl-dev` packages in the builder layer of the Dockerfile. 2024-01-28 14:38:01 -05:00
Zack 47fc96b98f
Merge pull request #645 from rehanone/fix-docker-deplyment
Update and fix the docker image deplyment build
2024-01-25 07:59:36 -08:00
Rehan Mahmood d4bba88fb1 Update and fix the docker image deplyment build 2024-01-25 10:02:01 -05:00
Zack Scholl c1367671b6 bump 9.6.6 2023-11-09 06:56:42 -08:00
Zack Scholl 1e572067ec bump 9.6.6 2023-11-09 06:56:29 -08:00
Zack Scholl 8aa9f040f6 bump 9.6.6 2023-11-09 06:53:42 -08:00
Zack Scholl 96bb34485e update deps 2023-11-09 06:51:31 -08:00
Zack 159f0f8d9b
Merge pull request #625 from gravetii/patch-1
Fix minor error in README
2023-11-05 07:30:14 -08:00
Sandeep c4d5c89e5f
Fix minor error in README 2023-11-03 11:20:41 +05:30
Zack 6ac67b68fc
Merge pull request #570 from PThorpe92/main
.gitignore support
2023-09-23 07:09:30 -07:00
PThorpe92 0af35d7149
feat: add support to respect .gitignore files 2023-09-22 21:15:27 -04:00
Zack f91c7a9948
Merge pull request #587 from ferebee/main
fix architecture detection for Apple Silicon
2023-09-03 19:35:53 -07:00
Zack cff8cddd13
Merge pull request #589 from zx9597446/main
zip file bug on windows and linux
2023-08-18 11:00:46 +02:00
zx9597446 d724f11297 Here is the English translation:
If there are directories in a zip file compressed on the Windows platform, the "\\" in the filepath will cause the files to be extracted normally on Linux, and ls will show filenames containing single quotes.

So when compressing, I replace "\\" with "/" so that it seems there are no issues on both Windows and Linux.
2023-08-17 12:07:07 +08:00
ferebee 80aabea29b fix architecture detection for Apple Silicon
fix auto-install on macOS Apple Silicon, which reports architecture "arm64" on uname -a rather than "aarch64"
2023-08-09 11:42:23 +02:00
sitiom f8bb011eac
switch winget releaser runner to `ubuntu-latest` 2023-07-07 08:52:14 +08:00
Zack Scholl ef68dfa54c bump 9.6.5 2023-07-06 10:10:57 -07:00
Zack Scholl 8ab65d06b5 bump 9.6.5 2023-07-06 10:10:39 -07:00
Zack Scholl 9c82914e7c update deps 2023-07-06 10:00:05 -07:00
Zack 95717f16c9
Merge pull request #579 from glitsj16/systemd-unit
croc.service: use DynamicUser
2023-06-21 05:58:58 -07:00
glitsj16 5a58ae294b
croc.service: use DynamicUser 2023-06-21 01:46:47 +00:00
Zack Scholl 0aa5c80393 upgrade dependencies 2023-05-08 17:39:18 +00:00
Zack 23a8904193
Merge pull request #563 from N0mansky/main
Feat: support http proxy as a complementary way to use in network limited environments.
2023-04-12 09:03:53 -07:00
N0mansky d5e63cd0bf Update: update error messages for http proxy 2023-04-12 18:17:25 +08:00
N0mansky 1b1dc5cdfe Feat: support http proxy as a complementary way to use in network limited environments. 2023-04-12 18:04:15 +08:00
Zack cd1162f85c
Merge pull request #553 from goggle/typos01
Fix some typos
2023-03-27 08:36:56 -07:00
Alexander Seiler ad7a22b218
Fix some typos
Signed-off-by: Alexander Seiler <seileralex@gmail.com>
2023-03-27 17:13:09 +02:00
Zack e3a18cd7a7
Merge pull request #547 from schollz/dependabot/github_actions/docker/setup-buildx-action-2
Bump docker/setup-buildx-action from 1 to 2
2023-03-27 07:43:21 -07:00
Zack 8611bfa44a
Merge pull request #550 from schollz/dependabot/github_actions/actions/setup-go-4
Bump actions/setup-go from 2 to 4
2023-03-27 07:42:58 -07:00
Zack Scholl b3c0625659 localhost -> 127.0.0.1 Fixes #513 2023-03-20 09:16:07 -07:00
dependabot[bot] 40e5893bb8
Bump actions/setup-go from 2 to 4
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 2 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-16 09:12:12 +00:00
Zack e1b49e6d1c
Merge pull request #549 from BayLee4/main
Enhance tab completion
2023-03-15 08:11:00 -07:00
BayLee4 fae2e81b4a
Enhance tab completion 2023-03-15 10:03:38 +01:00
BayLee4 f5a02df17b
Merge pull request #1 from schollz/main
Merge upstream
2023-03-15 07:40:29 +00:00
dependabot[bot] d813aa2fa9
Bump docker/setup-buildx-action from 1 to 2
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 2.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-14 12:01:02 +00:00
Zack 8d8d06557e
Merge pull request #534 from sitiom/winget-releaser
add winget releaser workflow
2023-03-14 05:00:19 -07:00
Zack Scholl 3ae46c3c18 bump 9.6.4 2023-03-14 04:52:15 -07:00
Zack Scholl 1fce28e72f remove twitter 2023-03-14 04:51:47 -07:00
Zack Scholl ac3caa5564 bump 9.6.4 2023-03-14 04:50:55 -07:00
Zack Scholl 790ee9e6eb bump 9.6.4 2023-03-14 04:50:29 -07:00
Zack Scholl 0656bb7851 bump 9.6.4 2023-03-14 04:50:10 -07:00
Zack Scholl 5ed8204cb1 bump 9.6.4 2023-03-14 04:50:00 -07:00
Zack Scholl 1220d54a65 bump 9.6.4 2023-03-14 04:41:22 -07:00
Zack Scholl 642d20b48d update deps 2023-03-14 04:39:05 -07:00
Zack 58bb226ba5
Merge pull request #542 from stefins/go-version
Upgrade Go version to 1.20 and dependencies to latest
2023-03-14 04:36:56 -07:00
stefins 080c21b66b
Change go version to 1.20 in CI 2023-03-10 20:59:45 +05:30
stefins 4944355b75
Upgrade Go version to 1.20 and dependencies to latest 2023-03-10 20:59:33 +05:30
Zack Scholl 3c1d60d6d2 bump 9.6.3 2023-02-20 07:34:32 -08:00
Zack Scholl 5bdd4453cd bump 9.6.3 2023-02-20 07:34:04 -08:00
Zack Scholl 5b333fc85c bump 9.6.3 2023-02-20 07:33:52 -08:00
Zack Scholl 90e4e33dcd bump 9.6.3 2023-02-20 07:33:34 -08:00
Zack Scholl 3135bd74e3 bump 9.6.3 2023-02-20 07:21:24 -08:00
Zack Scholl 7c98ae3d5a deps 2023-02-20 07:19:47 -08:00
sitiom 908f33cd61
add dependabot 2023-02-13 11:52:34 +08:00
sitiom 9eaba7be7c
add Winget installation instructions 2023-02-12 23:45:11 +08:00
Ryan Caezar Itang b3db9d88c1
add winget releaser workflow 2023-02-12 23:44:34 +08:00
Zack Scholl 9006cde1b3 update deps 2023-02-10 11:59:48 -08:00
Zack 8f75bb8299
Merge pull request #533 from stefins/patch-1
Update CI to run on main branch events
2023-02-10 11:59:21 -08:00
Zack faf64aadf1
Merge pull request #532 from stefins/chmod-file
Chmod new file based on the source file mode
2023-02-10 11:58:59 -08:00
stefins 65760b1189
Update CI to run on main branch events 2023-02-11 01:18:43 +05:30
stefins 24679d4e02
Chmod new file based on the source file mode 2023-02-10 14:53:06 +05:30
Zack Scholl 8b9977a7c4 update 2023-02-07 05:46:10 -08:00
Zack ae71b4b63b
Merge pull request #528 from chncaption/oscs_fix_cfds588au51u2n4fthm0
fix(sec): upgrade gopkg.in/yaml.v3 to 3.0.0
2023-02-07 05:45:44 -08:00
Zack Scholl c462b5948f update go.mod/go.sum 2023-02-07 05:44:17 -08:00
Zack a2c1dc6a89
Merge pull request #526 from BayLee4/main
Implement tab completion for words
2023-02-07 05:40:41 -08:00
chncaption 98391bff63 update gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c to 3.0.0 2023-02-02 22:03:21 +08:00
BayLee4 adadaba75e
Small optimization + consistent variable names style 2023-01-13 16:29:11 +01:00
BayLee4 0024beaedc
Implement tab completion for words 2023-01-12 19:23:50 +01:00
Zack Scholl 63feece074 add testing 2023-01-08 08:11:55 -08:00
Zack Scholl 9e280d7f48 update deps 2023-01-03 18:40:31 +00:00
Zack Scholl 7c7be95d6b update deps 2023-01-03 18:40:20 +00:00
Zack c20beb1be7
not reachable by twitter anymore 2022-12-16 16:35:06 -08:00
Zack Scholl e08c5e7f38 bump 9.6.2 2022-12-06 07:59:30 -08:00
Zack Scholl 3b819346fa bump 9.6.2 2022-12-06 07:58:30 -08:00
Zack Scholl 2467411bae fix install tests 2022-12-06 07:58:15 -08:00
Zack Scholl b436b31970 update deps 2022-12-06 07:45:07 -08:00
Zack Scholl e3ce565ca6 fix: allow remembering hash algorithm 2022-12-05 15:28:25 -08:00
Zack Scholl e04981698c update deps 2022-12-05 15:25:10 -08:00
Zack Scholl 07a67ed54e path -> fpath 2022-12-05 15:24:47 -08:00
Zack 9a8e584aca
Merge pull request #520 from taigrr/gofumpt
run through gofumpt
2022-12-05 15:22:10 -08:00
Tai Groot fa7ae114f5
run through gofumpt 2022-12-05 11:21:04 -08:00
Zack 8a4326bc0d
Merge pull request #519 from taigrr/workflow
update dockerfile to v1.19
2022-12-04 09:37:17 -08:00
Tai Groot ae20f2b5ac
update dockerfile 2022-12-01 21:45:10 -08:00
Zack Scholl cd6eb1ba53 update deps 2022-11-18 20:55:07 -08:00
Zack Scholl 8454008b45 update deps 2022-11-18 20:52:55 -08:00
Zack fce4629120
Merge pull request #515 from taigrr/workflow
Github CI go 1.18 -> 1.19
2022-11-18 20:47:36 -08:00
Tai Groot fd0db2ad55
upgrade github ci workflow 2022-10-30 20:43:51 -07:00
Zack 7f9688c7a1
Merge pull request #512 from IrishMaestro/revision
Typo fix
2022-10-23 10:29:05 -07:00
IrishMaestro f1e15a54ee
Typo fix
typo fix for the word relative
2022-10-22 17:18:16 -05:00
Zack Scholl 0f7f449d7f bump 9.6.1 2022-10-17 13:44:09 -07:00
Zack Scholl b27982a742 update deps 2022-10-17 13:42:39 -07:00
Zack Scholl 30f5a3e84e revert back to flate instead of zstd 2022-09-16 09:19:58 -07:00
Zack Scholl 786fc8d34f update mods 2022-09-16 09:10:08 -07:00
Zack 8de4508876
Merge pull request #506 from V-R-Dighe/develop
Added zstd as a compression algorithm
2022-09-16 09:08:14 -07:00
VRDighe e640e4fce0 Replaced zstd package 2022-09-16 10:19:44 +05:30
VRDighe 4f8b2aba9b Added zstd as a compression algorithm 2022-09-13 20:08:07 +05:30
Zack 1517767129
addresses #496 gettings ports doing LAN 2022-08-12 12:00:26 -07:00
Zack Scholl 3dedd41557 update 2022-08-06 09:32:46 -07:00
Zack 69f939c0cd
Merge pull request #494 from chavacava/fix-493
fix #493: data race in cli.relay
2022-08-05 08:38:07 -07:00
Zack cd5872bd2d
Merge pull request #497 from cuishuang/main
fix some typos
2022-08-05 08:37:36 -07:00
cui fliter 1c6583f925 fix some typos
Signed-off-by: cui fliter <imcusg@gmail.com>
2022-08-05 20:41:18 +08:00
chavacava 40ac320261
fix #493: data race in cli.relay 2022-07-17 10:40:49 +02:00
Zack Scholl 1851327df7 bump 9.6.0 2022-07-08 16:41:04 -07:00
Zack Scholl 0e93f1e285 println -> print os.stderr 2022-07-07 10:46:49 -07:00
Zack Scholl 7e0814a57e update deps 2022-07-07 10:34:20 -07:00
Zack Scholl c6bcb79928 remove zip compression and add --zip to send command 2022-07-07 10:32:23 -07:00
Zack 134673691e
Merge pull request #488 from stefins/zip-folder
Added ability to zip a directory
2022-07-07 10:14:23 -07:00
Stefin d226ba536e Fixed relative path / bug 2022-07-07 18:56:37 +05:30
Stefin b50fe88474 Added support for sending relative folder 2022-07-07 02:58:49 +05:30
Stefin 37ae453ff7 Unzipping file at the reciever end 2022-07-07 00:06:11 +05:30
Stefin ee772c4cec Added UnzipDirectory function 2022-07-07 00:05:56 +05:30
Stefin ed030375e5 Modified the argument for GetFilesInfo in tests 2022-07-06 18:49:32 +05:30
Stefin ad36e21051 Handling the --zip flag 2022-07-06 18:48:19 +05:30
Stefin 4ea9a96d88 Added --zip CLI argument for zipping all the dir specified 2022-07-06 18:47:34 +05:30
Stefin f0f9b80bdf added ZipDirectory function 2022-07-06 18:46:02 +05:30
Zack 7a0c0a8200
Merge pull request #474 from tjanez/fedora-package
add Fedora instructions to README
2022-05-20 09:50:31 -07:00
Zack Scholl 5270755c15 bump 9.5.6 2022-05-18 16:57:22 -07:00
Zack Scholl b7e4a73c27 don't show number of folders if the number is 0 2022-05-18 16:57:00 -07:00
Zack Scholl da5d19ef28 update deps and ui 2022-05-18 16:53:28 -07:00
Zack c68cfcea8a
Merge pull request #478 from DasSkelett/fix/relay-address-behind-dns64
Fix relay IPv4 address resolution behind DNS64
2022-05-18 16:48:51 -07:00
DasSkelett 38ed8ecc3c
Fix relay IPv4 address resolution behind DNS64 2022-05-16 22:04:55 +02:00
Tadej Janež a5d3e00f2b
add Fedora instructions to README 2022-04-29 22:31:59 +02:00
Zack Scholl 9de06a6bf9 bump 9.5.5 2022-04-28 14:30:03 -07:00
Zack Scholl a6a3a57361 update deps 2022-04-28 14:29:42 -07:00
Zack 148c1a6cdd
Merge pull request #470 from iulius98/master
Fixed #463 issue
2022-04-27 16:23:10 -07:00
Zack Scholl 817905cf5a bump 9.5.4 2022-04-27 08:25:06 -07:00
Zack Scholl 6158b42ad1 update deps 2022-04-27 08:23:43 -07:00
Zack Scholl 80539f27c3 avoid deadlock 2022-04-25 06:25:25 -07:00
Zack 35652e60a3
new support system 2022-04-13 06:42:08 -07:00
RCL98 2ad8b1f1ce #463 fixed display at receiving end 2022-04-13 02:23:10 +03:00
RCL98 b316c0159f #463 fixed croc tests for empty folders, and to work in Windows 2022-04-11 00:02:26 +03:00
RCL98 f78ee15605 #463 fixed display for empty folders 2022-04-11 00:00:47 +03:00
iulius98 15d0209a29 #463 added capability to send/receive empty folders 2022-04-09 01:38:22 +03:00
Zack 386c99d057
Merge pull request #462 from davide125/completion
Drop shebang for bash completion
2022-04-07 07:14:20 -07:00
Zack Scholl fd99a405fd bump 9.5.3 2022-04-07 06:05:16 -07:00
Zack Scholl 54f52e5427 bump 9.5.3 2022-04-07 06:04:46 -07:00
Zack Scholl ec949888d8 Merge branch 'master' of github.com:schollz/croc 2022-04-07 06:01:08 -07:00
Zack Scholl 0d52ead66e update default curve 2022-04-07 06:01:02 -07:00
Zack Scholl b715993435 bump 9.5.3 2022-04-07 05:59:24 -07:00
Zack Scholl 7e817e1cbf default to P-256 2022-04-07 05:52:54 -07:00
Zack 4abdbf1ad2
update to go 1.18 2022-04-06 21:48:39 -07:00
Zack Scholl 087c22d833 update readme 2022-04-03 15:21:35 -07:00
Zack Scholl 789b5bf607 update deps 2022-03-30 11:30:36 -07:00
Davide Cavalca e42f81a404 Drop shebang for bash completion 2022-02-27 08:40:56 -08:00
Zack Scholl 20bf7dd91d bump 9.5.2 2022-02-23 08:19:02 -08:00
Zack Scholl 4a8c19b115 bump 9.5.2 2022-02-23 08:16:50 -08:00
Zack Scholl a1a17ce6f7 bump 9.5.2 2022-02-23 08:09:02 -08:00
Zack Scholl 00c4d248fd bump 9.5.2 2022-02-23 08:08:43 -08:00
Zack Scholl 073196ccd2 bump 9.5.2 2022-02-23 08:07:23 -08:00
Zack Scholl 635b362ca0 tcp: send error on fail 2022-02-23 08:03:45 -08:00
Zack Scholl 53f35c1da0 fix ui when sending text 2022-02-23 07:57:40 -08:00
Zack 030ed2a03d
Merge pull request #456 from abhi12299/filenamePrefix
Fix renaming of file with prefix "croc-stdin" on receiver end
2022-02-23 07:52:27 -08:00
Zack Scholl c28d731a66 update deps 2022-02-23 07:31:45 -08:00
Zack Scholl ef6683b550 add more tests 2022-02-23 07:25:13 -08:00
Zack f6a75c8f53
Merge pull request #460 from iulius98/master
#431 fixed remote path
2022-02-23 07:14:46 -08:00
RCL98 7c1a59c102 #431 fixed remote folder name for Windows 2022-02-21 21:50:24 +02:00
iulius98 32a188fa85 #431 Integrate GetFilesInfo function with the code 2022-02-21 20:41:51 +02:00
RCL98 ce8fb796b3 #431 added file informations retrival functions to replace getPaths 2022-02-21 20:16:27 +02:00
Zack 1bd705d2e1
Merge pull request #459 from iulius98/master
#454 fixed local transfer
2022-02-20 07:57:34 -08:00
iulius98 1a635de69c #454 fixed local transfer 2022-02-20 17:40:50 +02:00
Zack 353ae0db16
add more information 2022-02-07 14:06:49 -08:00
Abhishek 9f66842322 fix sending file with prefix "croc-stdin" renaming on receiver end 2022-02-03 23:09:37 +05:30
Zack Scholl 94c0f66a26 bump 9.5.1 2022-02-03 08:51:19 -08:00
Zack Scholl b0e7d4d5df fix tests 2022-02-03 08:45:50 -08:00
Zack Scholl 9b5252d54c update deps 2022-02-03 08:40:49 -08:00
Zack Scholl 1d3c822ef3 allow remembering --internal-dns flag 2022-02-03 08:34:03 -08:00
Zack df78f3333d
Merge pull request #451 from voocel/fix_hash_err
fix hash file error
2022-01-06 04:43:50 -08:00
voocel b45e625298 fix hash file error 2022-01-06 17:44:43 +08:00
Zack Scholl 7390e7ed45 bump 9.5.0 2021-11-18 07:03:47 -08:00
Zack f210ef8877
Merge pull request #435 from AmeyShrivastava/fix-typos
Fix Typos
2021-11-17 10:52:29 -08:00
Amey Shrivastava 2964ede174 Fix Typos (revised)
This commit fixes spelling mistakes (typos) at a few places in the codebase.
(Includes requested corrections)
2021-11-17 23:50:32 +05:30
Zack Scholl cc837fa863 fix ports for tests 2021-11-17 10:11:35 -08:00
Zack Scholl 87bfdf11a8 update deps 2021-11-17 09:40:59 -08:00
Zack c30492609e
Merge pull request #432 from mbattista/master
added throttle upload feature
2021-11-17 09:37:50 -08:00
Zack 2f733891db
Merge pull request #440 from Juneezee/go1.17
build: upgrade to Go 1.17
2021-11-17 09:35:25 -08:00
Zack 3eb66284e0
Merge pull request #434 from HinWaei/fix4
Fixed an error
2021-11-17 09:33:48 -08:00
Eng Zer Jun 1645759742
refactor: move from io/ioutil to io and os packages
The io/ioutil package has been deprecated as of Go 1.16, see
https://golang.org/doc/go1.16#ioutil. This commit replaces the existing
io/ioutil functions with their new definitions in io and os packages.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-11-17 11:39:11 +08:00
Eng Zer Jun da8beb65bf
build: upgrade to Go 1.17
Go 1.17 introduces compiler improvement
(https://golang.org/doc/go1.17#compiler) and supports module graph
pruning (https://golang.org/ref/mod#graph-pruning) and lazy module
loading (https://golang.org/ref/mod#lazy-loading).

This commit applies the changes by running `go mod tidy -go=1.17` to
enable module graph pruning and lazy module loading supported by Go 1.17
or higher.

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2021-11-17 11:39:01 +08:00
Hinux Chau d30433658b
Fixed an error
Fixed an error caused by nonexistence of the directory /etc/bash_completion.d/croc
2021-10-27 22:21:31 +08:00
Marcel Battista d372fa1fa4 fix panic on single digit throttles values 2021-10-19 13:10:43 +02:00
Marcel Battista 8ff3fb9b89 added throttle upload feature 2021-10-19 02:46:54 +02:00
Zack 696479024e
Update ci.yml 2021-10-08 09:43:30 -07:00
Zack 9dfa0284fa update with setup 2021-10-08 09:39:20 -07:00
Zack Scholl a12f374aba can't use the github ci 8084 2021-10-04 08:02:27 -07:00
Zack 8ee1825f84
Merge pull request #424 from jolheiser/fix-const
Fix TCP constant
2021-10-04 07:29:27 -07:00
Zack f99c33d794
Merge pull request #426 from maximbaz/ci
Run tests via Github Actions
2021-10-04 07:26:53 -07:00
Maxim Baz 417b371454
Add CI 2021-10-04 00:16:49 +02:00
jolheiser 2ffb20201c
Fix TCP constant
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2021-10-03 16:23:29 -05:00
Zack Scholl 89efd38c10 bump 9.4.2 2021-10-02 12:38:32 -07:00
Zack Scholl 49f50a53d5 need to listen on all ports 2021-10-02 12:37:16 -07:00
Zack Scholl 5d9afe03ef bump 9.4.1 2021-10-02 12:29:05 -07:00
Zack Scholl 1637765aad debugging 2021-10-02 12:23:36 -07:00
Zack Scholl ce628ea604 debugging 2021-10-02 12:20:18 -07:00
Zack Scholl ff4307c3c6 debugging 2021-10-02 12:18:50 -07:00
Zack Scholl e5f59fa0f9 fix local 2021-10-02 12:02:25 -07:00
Zack Scholl 04662df347 fix local 2021-10-02 11:55:43 -07:00
Zack Scholl 4ea66fbd18 upgrade peerdiscovery 2021-10-02 10:55:12 -07:00
Zack Scholl d96c98f4ce bump 9.4.0 2021-10-02 10:45:00 -07:00
Zack Scholl 31db6a76e5 bump 9.4.0 2021-10-02 10:44:48 -07:00
Zack Scholl a996f3c4f4 bump 9.4.0 2021-10-02 10:44:34 -07:00
Zack Scholl 4334c870f5 bump 9.4.0 2021-10-02 10:44:17 -07:00
Zack Scholl 2b1367a09b bump 9.4.0 2021-10-02 10:44:05 -07:00
Zack Scholl add1650cbd bump 9.4.0 2021-10-02 10:43:14 -07:00
Zack Scholl 04f2dfac97 bump 9.4.0 2021-10-02 10:41:46 -07:00
Zack Scholl 060ce516b1 bump 9.4.0 2021-10-02 10:41:26 -07:00
Zack Scholl 78b6f2d858 update deps 2021-10-02 10:37:20 -07:00
Zack d77c83ce09
Merge pull request #419 from kallydev/patch
Add host flag for relay
2021-10-02 10:35:00 -07:00
Zack a34d29befc
Merge pull request #420 from jolheiser/const
Constants and Message Types
2021-10-02 10:33:52 -07:00
Zack 914d0c98a8
Merge pull request #421 from jolheiser/wildcard
Add wildcard support for files
2021-10-02 10:33:15 -07:00
Zack 55cb35d12b
Merge pull request #422 from BrandonIngalls/gh-405-config-defaults
Do not override defaults with empty values
2021-10-02 10:29:40 -07:00
Brandon Ingalls 860a75fee6 Do not override defaults with empty values
This change will make it so a user who used the -remember
option on an older version of the application will be able
to use the latest version of the software without deleting
their saved config.

fixes schollz/croc#405
relates to schollz/croc#417
2021-10-02 11:12:34 -05:00
jolheiser e380c7b1f1
Add wildcard support
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2021-10-01 16:49:21 -05:00
jolheiser 2381f26c61
Move to consts and "enum"
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2021-10-01 16:24:28 -05:00
KallyDev de454bbf5a
add host flag for relay 2021-10-01 12:55:28 +08:00
Zack Scholl e19e06a652 update deps 2021-09-14 10:44:33 -07:00
Zack 6deafaadae
Merge pull request #412 from adworacz/sendMultifileDocs
Clarify croc's ability to send multiple files/folder
2021-08-29 10:51:04 -07:00
Austin Dworaczyk Wiltshire ef3953a586 Clarify croc's ability to send multiple files/folder
I was personally shocked that I could send multiple files via croc
recently, having done it purely on a whim. The existing CLI
documentation makes no mention of croc's ability to send multiple
files/folders.

This adds it.
2021-08-29 10:16:51 -07:00
Zack Scholl 1d3fdffed6 bump 9.3.0 2021-08-16 12:29:43 -07:00
Zack Scholl 94b2aff637 update deps 2021-08-16 12:28:26 -07:00
Zack 9ce2321d01
Merge pull request #409 from CHTJonas/master
Make internal DNS resolution opt-in
2021-08-16 12:27:57 -07:00
Charlie Jonas d75530b78b Improve built-in list of public DNS recursors 2021-08-16 18:48:03 +01:00
Charlie Jonas f64f68d5a9 Tidy up code slightly 2021-08-16 18:47:25 +01:00
Charlie Jonas be7705efc3 Remove DNS lookup timeouts 2021-08-16 18:32:55 +01:00
Charlie Jonas df2e29b74d Add --internal-dns flag 2021-08-16 18:25:34 +01:00
Zack Scholl b73fdff702 mv goreleaser 2021-08-06 14:35:53 -07:00
Zack Scholl 664936feb2 bump 9.2.1 2021-08-06 13:46:23 -07:00
Zack Scholl 4b1eb6519c update deps 2021-08-06 13:45:23 -07:00
Zack Scholl 86aeed93db move mutex to avoid race condition #407 2021-08-06 09:48:26 -07:00
Zack Scholl 7993e73ac2 update deps 2021-07-29 13:43:21 -07:00
Zack Scholl d922808fd8 change install cmd 2021-06-25 13:19:23 -07:00
Zack Scholl 8d22737fd3 bump 9.2.0 2021-06-21 11:54:11 -07:00
Zack Scholl d442755814 show preparing progress 2021-06-21 11:11:44 -07:00
Zack Scholl 0afdf71305 update deps 2021-06-21 07:43:20 -07:00
Zack Scholl ecf3eb872e allow selecting hash 2021-06-21 07:34:28 -07:00
Zack Scholl 646c879edc bump 9.1.6 2021-06-15 15:08:32 -07:00
Zack Scholl cbe9cbe32a update deps 2021-06-15 14:54:22 -07:00
Zack Scholl 4796404b7e show resume message if resuming
Fixes #402
2021-06-15 14:53:16 -07:00
Zack Scholl 3e2c88c5bc bump 9.1.5 2021-06-10 14:45:24 -07:00
Zack Scholl 0124356cd7 update deps 2021-06-10 14:44:49 -07:00
Zack f2ef6f19a5
Merge pull request #401 from nikoksr/refactor/accept-enter-in-prompts
refactor: Accept enter in prompts
2021-06-10 14:43:11 -07:00
Niko Köser 5e0d6522b0
refactor: accept enter in user prompts
Until now, the process of receiving a file was aborted when an
empty entry (Enter) was made. It is common under *nix that
pressing Enter without prior input of other characters selects
the default answer. This would also make the process more
fluid for croc.

In most usecases the default choice will be 'Y'/'Yes'. The only
exception is the prompt for overwriting existing files. We default
to 'N'/'No' in this prompt to prevent accidental overwriting of
files.
2021-06-10 14:12:05 +02:00
Niko Köser c72aaf63cb
chore(git): ignore .idea and .vscode folders 2021-06-09 16:00:09 +02:00
Zack Scholl a9e77673f4 update deps 2021-05-12 12:04:30 -07:00
Zack Scholl aa93d3e30f Merge branch 'master' of github.com:schollz/croc 2021-05-12 07:19:09 -07:00
Zack Scholl 15a19e1998 use all the config options 2021-05-12 07:19:02 -07:00
Zack Scholl e1ccb58d8f bump 9.1.4 2021-05-12 07:04:38 -07:00
Zack Scholl d0ebb7ad38 longer time for local connections 2021-05-12 07:04:10 -07:00
Zack Scholl 2bfbacf972 bump 9.1.3 2021-05-11 10:06:14 -07:00
Zack Scholl e29b4c47fd update deps 2021-05-11 10:05:37 -07:00
Zack Scholl b4deedf367 upgrade peerdiscovery 2021-05-11 10:04:21 -07:00
Zack Scholl 68e507dbba update peerdiscovery 2021-05-11 07:09:56 -07:00
Zack Scholl 66f30c0565 skip autocomplete installation on fish, Fixes #393 2021-05-10 13:47:17 -07:00
Zack Scholl 340bafba3d bump 9.1.2 2021-05-07 10:23:45 -07:00
Zack Scholl e47776bb10 fix 2021-05-07 10:21:24 -07:00
Zack 422f099e5e
Merge pull request #390 from wamserma/patch-1
Distinguish text message from file in receipient dialog
2021-05-07 10:20:53 -07:00
Zack Scholl bd4886ae3c update deps 2021-05-07 10:18:40 -07:00
Markus Wamser d5fd2060dd
Distinguish text message from file in receipient dialog
Fixes https://github.com/schollz/croc/issues/388
2021-05-01 21:27:44 +02:00
Zack Scholl 7c28279a58 bump 9.1.1 2021-04-29 09:43:50 -07:00
Zack Scholl 27b7cdbf12 bug fix: doesn't ask overwrite text Fixes #384 2021-04-29 09:16:22 -07:00
Zack Scholl 24fb8746a4 fix deadlock 2021-04-29 09:11:29 -07:00
Zack 45cb545a82
Merge pull request #383 from oxzi/dns-prefer-local
Prefer local DNS resolver over public DNS servers
Fixes #301
2021-04-26 10:45:07 -07:00
Alvar Penning 8f5c73837a Prefer local DNS resolver over public DNS servers
The changes cause the local DNS resolver to be used exclusively at
first. If this fails, the public DNS servers are queried as before.

This feature was previously requested. Merging should close #301.

Along the way, three other changes are introduced:

1. A public IPv6 DNS server was added.

2. The lookup returns the first result from a public DNS server and does
   not wait for all queries to be answered.

3. In the unlikely case that no public DNS server is able to answer, an
   error will be returned.
2021-04-26 11:43:45 +02:00
Zack b90f9329ca
Merge pull request #376 from Craeckie/master
Use unprivileged user in docker
2021-04-23 10:28:22 -07:00
Craeckie 968950f783
Use unprivileged user in docker
See 
https://americanexpress.io/do-not-run-dockerized-applications-as-root/
and 
https://engineering.bitnami.com/articles/why-non-root-containers-are-important-for-security.html
2021-04-22 09:53:49 +00:00
Zack Scholl 5b0883e1fe generate key once 2021-04-21 16:57:18 -07:00
Zack Scholl 420030998f add chacha20 2021-04-21 16:53:29 -07:00
Zack Scholl de2bcf114c upgrade imohash 2021-04-21 14:36:50 -07:00
Zack Scholl ab5ae5cbb6 add more benchmarks 2021-04-21 12:40:41 -07:00
Zack Scholl 94b3dba034 update readme 2021-04-20 16:01:44 -07:00
Zack 1a47543be9
Merge pull request #344 from k3b/patch-1
Added reference to croc android-version to README.md
2021-04-20 15:59:44 -07:00
Zack Scholl 407e162ec2 bump 9.1.0 2021-04-20 15:57:46 -07:00
Zack 35106d4dbe
Merge pull request #374 from schollz/v91
V91
2021-04-20 15:55:19 -07:00
Zack Scholl d6af319ad8 fix tests 2021-04-20 15:48:13 -07:00
Zack Scholl 85e7576311 fix 2021-04-20 15:44:28 -07:00
Zack Scholl 7ac7be37af check if file exists 2021-04-20 15:36:46 -07:00
Zack Scholl 669aeb377a check if file exists 2021-04-20 15:35:38 -07:00
Zack Scholl b655afb533 choose hash algorithm 2021-04-20 15:32:05 -07:00
Zack Scholl e9949ce3d7 check file size firsty 2021-04-20 09:08:02 -07:00
Zack Scholl 91a3dd5866 Merge branch 'master' of github.com:schollz/croc 2021-04-17 20:42:20 -07:00
Zack Scholl 026487a833 update docker 2021-04-17 20:40:56 -07:00
Zack Scholl f8ef096784 bump 9.0.0 2021-04-17 20:33:18 -07:00
Zack Scholl 0c2089bd4c update deps 2021-04-17 20:32:55 -07:00
Zack Scholl 5ad68b9ced update readme 2021-04-17 20:31:17 -07:00
Zack Scholl 9286b3c965 show folders when receiving 2021-04-17 20:27:51 -07:00
Zack Scholl c1edf24338 fix race condition 2021-04-17 20:07:50 -07:00
Zack Scholl d38fc18390 update deps 2021-04-17 14:31:32 -07:00
Zack Scholl f4cedd1e91 Merge branch 'master' of github.com:schollz/croc 2021-04-17 11:27:25 -07:00
Zack Scholl fc66c3b91f improve readme 2021-04-17 11:27:20 -07:00
Zack Scholl 2ac7d4f31f fix tests 2021-04-17 11:12:15 -07:00
Zack Scholl a96762b942 fix room deletion if room is full 2021-04-17 10:44:10 -07:00
Zack Scholl 0a0f7a03d7 update version 2021-04-17 10:33:38 -07:00
Zack Scholl 8148e191ae bump 2021-04-17 17:31:44 +00:00
Zack Scholl 25a985464a Merge branch 'master' of github.com:schollz/croc 2021-04-17 17:15:02 +00:00
Zack 333ece706e
Merge pull request #369 from schollz/v9
V9
2021-04-17 10:12:42 -07:00
Zack Scholl daf10395a3 update deps 2021-04-17 09:42:11 -07:00
Zack Scholl 9231b1a661 update utils benchmark 2021-04-17 09:39:47 -07:00
Zack Scholl 3e56d4cdb9 use magic bytes instead of checking max 2021-04-17 09:05:27 -07:00
Zack Scholl cec39ba2ce allow changing curve 2021-04-17 09:01:58 -07:00
Zack Scholl 7a997156ed minor 2021-04-16 17:17:32 -07:00
Zack Scholl c02b4f1256 fix: make sure that only pake messages are unencrypted 2021-04-16 17:15:51 -07:00
Zack Scholl babfd5f35f add option to overwrite automatically 2021-04-16 15:14:21 -07:00
Zack Scholl be5ceae8c7 prompt to overwrite 2021-04-16 15:12:11 -07:00
Zack Scholl 6be4080f05 remove hash exchange 2021-04-16 14:25:57 -07:00
Zack Scholl b0693751c1 fix 2021-04-16 14:01:48 -07:00
Zack Scholl 8250a39534 fix: delete room if full and third-party tries to enter 2021-04-16 09:48:11 -07:00
Zack Scholl 2131e99826 use new pake 2021-04-16 09:20:13 -07:00
Zack Scholl 628043b228 fix: do not use part of secret as room name 2021-04-16 08:13:43 -07:00
Zack Scholl 362a30e5e7 Merge branch 'master' of github.com:schollz/croc 2021-04-15 22:05:04 +00:00
Zack 828de41d6c
Merge pull request #361 from tdussa/BrokenSymlink
Transfer symlinks without touching their targets.
2021-04-15 15:01:49 -07:00
Tobias Dussa 876ce5764b Transfer symlinks without touching their targets. 2021-04-15 17:07:23 +02:00
Zack Scholl 59b287df7f Merge branch 'master' of github.com:schollz/croc 2021-04-13 22:40:03 +00:00
Zack 3fd125178f
Merge pull request #341 from MatejKafka/master
Added CROC_CONFIG_DIR env var to support custom config dir path
2021-04-13 15:38:38 -07:00
Zack 136faac448
Merge pull request #355 from stingalleman/patch-1
Remove dollar icons from commands without output
2021-04-13 15:37:22 -07:00
Zack 85a0bfb898
Merge pull request #359 from mizzunet/patch-1
Enhancements to bug_report.md
2021-04-13 15:36:39 -07:00
Missu 4718f3897c
Commented, added bug label
Commented lines need to be manually removed by the user, so no need to remove those anymore
Added "big" label for this, so easily discoverable from the Issues list
2021-04-08 11:42:19 +05:30
Sting Alleman 068d5c1031
Remove dollar icons from commands without output 2021-04-04 22:57:14 +02:00
Zack Scholl 4dfa1a9236 Merge branch 'master' of github.com:schollz/croc 2021-03-26 23:05:01 +00:00
Zack Scholl 6ba6ec9d32 bump 8.6.12 2021-03-26 16:03:51 -07:00
Zack Scholl c373b38b59 bump 8.6.12 2021-03-26 16:03:31 -07:00
Zack Scholl f2af5b7256 don't know why , but won't compile for freebsd/arm
⨯ release failed after 348.00s error=failed to build for freebsd_arm_7: # golang.org/x/net/ipv4
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:37:79: undefined: unix.MCAST_JOIN_GROUP
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:38:79: undefined: unix.MCAST_LEAVE_GROUP
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:39:79: undefined: unix.MCAST_JOIN_SOURCE_GROUP
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:40:79: undefined: unix.MCAST_LEAVE_SOURCE_GROUP
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:41:79: undefined: unix.MCAST_BLOCK_SOURCE
../../../../pkg/mod/golang.org/x/net@v0.0.0-20210326220855-61e056675ecf/ipv4/sys_freebsd.go:42:79: undefined: unix.MCAST_UNBLOCK_SOURCE
2021-03-26 16:02:39 -07:00
Zack Scholl 483f840401 Merge branch 'master' of github.com:schollz/croc 2021-03-26 22:45:03 +00:00
Zack Scholl ff12c33e7f bump 8.6.12 2021-03-26 15:41:45 -07:00
Zack Scholl e4cecf670b update deps 2021-03-26 15:41:13 -07:00
Zack Scholl 94e0e3ca67 Merge branch 'master' of github.com:schollz/croc 2021-03-26 22:40:03 +00:00
Zack Scholl a9d582cc6a lookup using standard dns 2021-03-26 15:39:33 -07:00
k3b ab9396937c
Added reference to croc android-version to README.md
See https://f-droid.org/en/packages/com.github.howeyc.crocgui/ for details
2021-03-25 12:32:17 +01:00
Matej Kafka c1e546ede6
Added CROC_CONFIG_DIR env var to support custom config dir path 2021-03-20 00:50:50 +01:00
Zack Scholl 63ba28c9b0 Merge branch 'master' of github.com:schollz/croc 2021-03-17 17:20:04 +00:00
Zack 6caf72df82
Merge pull request #340 from jfaltis/xdg-basedir-spec-compliance
Add compliance with XDG Base Directory Specification (XDG_CONFIG_HOME)
2021-03-17 10:17:52 -07:00
Jona 2273438373 add compliance with xdg base directory specification in regards to XDG_CONFIG_HOME 2021-03-17 17:45:07 +01:00
Zack Scholl 50a0d86e3d Merge branch 'master' of github.com:schollz/croc 2021-03-15 19:40:02 +00:00
Zack Scholl 50aa24d86d bump 8.6.11 2021-03-15 12:39:04 -07:00
Zack Scholl 674bff7a13 Merge branch 'master' of github.com:schollz/croc 2021-03-15 19:35:03 +00:00
Zack Scholl 757ed180fb update deps 2021-03-15 12:31:07 -07:00
Zack Scholl 76648a2926 Merge branch 'master' of github.com:schollz/croc 2021-03-15 19:05:04 +00:00
Zack Scholl 0b76edc362 update deps 2021-03-15 12:04:48 -07:00
Zack Scholl c39061c7fc Merge branch 'master' of github.com:schollz/croc 2021-03-15 18:55:03 +00:00
Zack Scholl fb2723d80b don't show description if only sending one file 2021-03-15 11:50:30 -07:00
Zack Scholl f84341a197 Merge branch 'master' of github.com:schollz/croc 2021-03-10 16:20:03 +00:00
Zack 6e9156d49c
Merge pull request #337 from alrs/alrs-fix-server-nil-salt-and-keys
src/tcp: fix dropped errors
2021-03-10 08:16:19 -08:00
Zack cd6d9a5aa0
Merge pull request #338 from alrs/alrs-fix-client-swallowed-errs
src/croc: fix dropped errors
2021-03-10 08:16:06 -08:00
Lars Lehtonen 3e5b876a32
src/croc: fix dropped errors 2021-03-09 16:55:42 -08:00
Lars Lehtonen a9487a332c
src/tcp: fix dropped errors 2021-03-09 16:48:38 -08:00
Zack Scholl de924f6a4f Merge branch 'master' of github.com:schollz/croc 2021-03-08 16:45:04 +00:00
Zack Scholl 03a27b6683 bump 8.6.10 2021-03-08 08:41:54 -08:00
Zack Scholl 0b719b9b77 update deps 2021-03-08 08:41:17 -08:00
Zack Scholl fc34d21cb8 thanks 2021-03-08 08:41:00 -08:00
Zack Scholl bb05d48fe9 Merge branch 'master' of github.com:schollz/croc 2021-03-08 16:40:02 +00:00
Zack 949480517f
Merge pull request #336 from hreese/master
Added support for SOCKS5 authentication (fixes #333)
2021-03-08 08:38:27 -08:00
Heiko Reese a20ebd7120 Added support for SOCKS5 authentication (fixes #333) 2021-03-06 11:55:16 +01:00
Zack Scholl d49bb8632b Merge branch 'master' of github.com:schollz/croc 2021-03-05 19:05:02 +00:00
Zack Scholl 10e57c3f97 bump 8.6.9 2021-03-05 11:02:51 -08:00
Zack Scholl be95662e35 update deps 2021-03-05 11:01:51 -08:00
Zack Scholl 105fb9a3ce Merge branch 'master' of github.com:schollz/croc 2021-03-05 17:05:02 +00:00
Zack Scholl 30783ce79c overwrite symlinks on transfer, like files, fixes #334 2021-03-05 09:00:15 -08:00
Zack Scholl a46f09ee1c Merge branch 'master' of github.com:schollz/croc 2021-02-23 20:15:02 +00:00
Zack Scholl cdabf629b6 bump 8.6.8 2021-02-23 12:10:30 -08:00
Zack Scholl 40cda1bed7 Merge branch 'master' of github.com:schollz/croc 2021-02-23 20:10:04 +00:00
Zack Scholl 92ab62d03e bump 8.6.8 2021-02-23 12:09:50 -08:00
Zack Scholl 31012b8f7d fix goreleaser 2021-02-23 12:09:42 -08:00
Zack Scholl 4b0d01d8f0 bump 8.6.8 2021-02-23 12:06:59 -08:00
Zack Scholl 648eb6c71d update deps 2021-02-23 12:03:29 -08:00
Zack Scholl b19a028aea Merge branch 'master' of github.com:schollz/croc 2021-02-19 18:30:03 +00:00
Zack 9588f2b4a4
Merge pull request #331 from schollz/dns
Dns
2021-02-19 10:25:32 -08:00
Zack Scholl cd2802b8b5 shorter dns fail time 2021-02-19 10:18:13 -08:00
Zack Scholl c5ff55a193 find dns from any number of providers 2021-02-19 10:16:58 -08:00
Zack Scholl 1cf309faf2 Merge branch 'master' of github.com:schollz/croc 2021-02-11 22:10:05 +00:00
Zack 8dc5bd6e04
Merge pull request #328 from lekoOwO/patch-1
Add alpine linux installation instructions
2021-02-11 14:06:29 -08:00
leko 37f09049a4
Update README.md 2021-02-11 15:19:11 +08:00
Zack Scholl eaa18cd502 Merge branch 'master' of github.com:schollz/croc 2021-02-10 17:40:04 +00:00
Zack Scholl b9d461e5df update deps 2021-02-10 09:36:42 -08:00
Zack Scholl 89ea0166fa Merge branch 'master' of github.com:schollz/croc 2021-02-03 18:10:04 +00:00
Zack Scholl 77fd78e408 Merge branch 'master' of github.com:schollz/croc 2021-02-03 10:08:40 -08:00
Zack Scholl edeb7c8886 update deps 2021-02-03 10:08:30 -08:00
Zack Scholl 4481fe2336 Merge branch 'master' of github.com:schollz/croc 2021-02-02 14:50:03 +00:00
Zack ef43873c3b
Merge pull request #325 from nikoksr/fix/missing-code-too-short-error
fix(cli): make 'code too short' error symmetric on both sender and receiver side
2021-02-02 06:48:21 -08:00
Zack Scholl 0bec0b26ab Merge branch 'master' of github.com:schollz/croc 2021-02-02 14:45:04 +00:00
Zack 681c824ef4
remove snap, it just doesn't work 2021-02-02 06:43:12 -08:00
Zack Scholl 950b6f83d9 Merge branch 'master' of github.com:schollz/croc 2021-02-01 15:00:03 +00:00
Zack Scholl 7f5d704a26 change name 2021-02-01 06:58:27 -08:00
Zack a6a8ab71ce
Merge pull request #315 from PeterEve/master
Added an option to ignore attached stdin.
2021-02-01 06:56:45 -08:00
Zack de56d2f6dd
Merge pull request #321 from Spaceface16518/docker-min
Reduce size of Docker image by stripping debug symbols
2021-02-01 06:55:08 -08:00
Zack Scholl 2f96b77b73 Merge branch 'master' of github.com:schollz/croc 2021-02-01 14:55:02 +00:00
Zack 0548c2e45f
Merge pull request #322 from benjamin-wen/patch-1
Update year
2021-02-01 06:54:42 -08:00
Niko Köser 0b60fef246
refactor: write errors into stderr and add exit code
Instead of writing errors into stdout and alway returning exit code 0,
we now write into stderr and return exit code 1 in case that an error
occured.
2021-02-01 10:48:34 +01:00
Niko Köser 3ccd4d07e9
fix: accidentally overwritten error value
In function _cli.send_ the named return value 'err' gets accidentally
overwritten in the deferred anonymous function that removes the
files/directories. Renamed the error variable inside the deferred
function so that it does not overwrite the original error anymore.

Closes #296
2021-02-01 10:34:06 +01:00
Benjamin Wen b5f1b35213
Update year 2021-01-28 11:27:27 +08:00
Spaceface16518 90eda5639f Strip go binary in docker build 2021-01-27 12:30:45 -06:00
Zack Scholl 77d0c7ae2e Merge branch 'master' of github.com:schollz/croc 2021-01-26 21:20:03 +00:00
Zack 493eb075f1
Merge pull request #318 from Spaceface16518/master
Docker deployment configuration
2021-01-26 13:16:23 -08:00
Spaceface16518 247d2b18ec Remove linux/ppc64le platform
gcc not found in $PATH?
2021-01-22 00:00:20 -06:00
Spaceface16518 6b8a14d831 Remove linux/s390x platform
Breaking the docker buildx build due to some signature verification
error
2021-01-22 00:00:20 -06:00
Amrit 743b2c1bf4
Create deploy.yml 2021-01-21 23:32:51 -06:00
Peter 17f3df7e36 Added an option to ignore attached stdin, for compatibility with node child_process 2021-01-10 13:17:43 +00:00
Zack Scholl dab683c9dc Merge branch 'master' of github.com:schollz/croc 2020-12-29 17:35:03 +00:00
Zack e829ca0ff4
thank you digital ocean 2020-12-29 09:34:57 -08:00
Zack Scholl e27c32cf6e Merge branch 'master' of github.com:schollz/croc 2020-12-28 19:05:03 +00:00
Zack Scholl a2b243ad94 bump 8.6.7 2020-12-28 11:01:27 -08:00
Zack Scholl 05640cd49f update deps 2020-12-28 11:00:44 -08:00
Zack Scholl 037dbbd4e9 Merge branch 'master' of github.com:schollz/croc 2020-12-28 18:50:06 +00:00
Zack 0994e4eda5
Merge pull request #307 from hillmarcus/306-file-size
Issue #306, File Size Mismatch
2020-12-28 10:46:39 -08:00
Zack 235f065a9c
Merge pull request #310 from vzlcn0/master
add new cmd option to set sender ip
2020-12-28 10:46:14 -08:00
vzlcn0 52bc6312e1 add new cmd option to set sender ip 2020-12-17 18:37:48 +03:00
Marcus d735cca970 Issue #306, File Size Mismatch
Updated utils.go to use a `1024` grouping instead of `1000` for file
sizes. This brings it inline with the progress bar project being used.

Updated utils_test.go to match the changes to utils.go
2020-12-07 18:44:12 -06:00
Zack Scholl af5ba6ead8 Merge branch 'master' of github.com:schollz/croc 2020-11-18 00:15:04 +00:00
Zack Scholl 5978896936 bump 8.6.6 2020-11-17 16:10:57 -08:00
Zack Scholl 2ffafd4607 Merge branch 'master' of github.com:schollz/croc 2020-11-18 00:10:04 +00:00
Zack Scholl e7ed4fc05f update deps 2020-11-17 16:09:29 -08:00
Zack Scholl 1da2f58a53 faster dns resolution on startup 2020-11-17 10:46:49 -08:00
Zack Scholl 284af7fc7a hm 2020-11-17 10:35:57 -08:00
Zack Scholl dbc4a08ad0 use google for lookup 2020-11-17 10:29:52 -08:00
Zack Scholl c55e9be0ef Merge branch 'master' of github.com:schollz/croc 2020-10-23 15:30:05 +00:00
Zack Scholl b740e491e6 bump 8.6.5 2020-10-23 08:26:15 -07:00
Zack Scholl 10ed62cfd5 Merge branch 'master' of github.com:schollz/croc 2020-10-23 15:05:03 +00:00
Zack Scholl 8d430b6cb1 update progressbar 2020-10-23 07:59:56 -07:00
Zack Scholl cdb1981358 Merge branch 'master' of github.com:schollz/croc 2020-10-23 00:05:04 +00:00
Zack Scholl f51ea8bfdc show progress 2020-10-22 17:03:46 -07:00
Zack Scholl a45e66733b Merge branch 'master' of github.com:schollz/croc 2020-10-22 17:20:05 +00:00
Zack Scholl 23f97c61ac bump 8.6.4 2020-10-22 10:18:40 -07:00
Zack Scholl cbb728b9a2 bump 8.6.4 2020-10-22 10:17:58 -07:00
Zack Scholl 9bb2d2b7cc bump 8.6.4 2020-10-22 10:17:33 -07:00
Zack Scholl 3f10a147dd bump 8.6.4 2020-10-22 10:16:55 -07:00
Zack Scholl d112f43f63 Merge branch 'master' of github.com:schollz/croc 2020-10-22 17:15:04 +00:00
Zack Scholl bf9ebfc4b4 show ping 2020-10-22 10:13:41 -07:00
Zack Scholl d3aa2be9ab ping server from discoveries 2020-10-22 10:11:11 -07:00
Zack Scholl 034e012227 allow pinging 2020-10-22 10:09:04 -07:00
Zack Scholl 05c82809c6 Merge branch 'master' of github.com:schollz/croc 2020-10-22 17:05:04 +00:00
Zack Scholl 79f85fda9b bug fix: return if found error 2020-10-22 09:59:55 -07:00
Zack Scholl 6ad8e08b0c Merge branch 'master' of github.com:schollz/croc 2020-10-22 16:55:03 +00:00
Zack Scholl 3bcc83a8fc gather all discoveries 2020-10-22 09:53:27 -07:00
Zack Scholl 6c86188564 Merge branch 'master' of github.com:schollz/croc 2020-10-22 14:45:05 +00:00
Zack Scholl 1d9393d39b bump 8.6.3 2020-10-22 07:40:56 -07:00
Zack Scholl 4663df1059 Merge branch 'master' of github.com:schollz/croc 2020-10-22 14:40:04 +00:00
Zack 817e0b78f6
Merge pull request #293 from nkhang/features/show-passphrase-issue
fix(cli): show passphrase when user indicate --pass
2020-10-22 07:40:01 -07:00
Khang. Nguyen Khac Nguyen 4070f12cbf change(croc): shorten flag with builder 2020-10-22 14:06:54 +07:00
Khang. Nguyen Khac Nguyen 8e50b59671 fix(cli): show passphrase when user indicate --pass
+ when user indicate --pass when sending file, indicate --pass flag in
recommended receive command.
2020-10-22 13:37:32 +07:00
Zack Scholl 61ffdc61f3 Merge branch 'master' of github.com:schollz/croc 2020-10-21 19:55:03 +00:00
Zack Scholl ff45ccd346 bump 8.6.2 2020-10-21 12:52:53 -07:00
Zack Scholl 5a791e98af bump 8.6.2 2020-10-21 12:51:47 -07:00
Zack Scholl 0d767af80a fix makefile 2020-10-21 12:51:43 -07:00
Zack Scholl bb971a9937 bump 8.6.1 2020-10-21 12:50:30 -07:00
Zack Scholl c88d3ad62a update makefile 2020-10-21 12:50:25 -07:00
Zack Scholl 1a242711cc Merge branch 'master' of github.com:schollz/croc 2020-10-21 17:30:05 +00:00
Zack Scholl 77732c49a0 bump 8.6.0 2020-10-21 10:28:28 -07:00
Zack Scholl b9b22ad041 bump 8.6.0 2020-10-21 10:28:27 -07:00
Zack Scholl 7a73e4912c allow using only local with --local flag 2020-10-21 18:25:56 +01:00
Zack Scholl 3129b097af use only local 2020-10-21 10:23:12 -07:00
Zack Scholl 1967ef57be bump 8.5.3 2020-10-21 09:41:08 -07:00
Zack Scholl b95c2c781b bump 8.5.3 2020-10-21 09:41:07 -07:00
Zack Scholl ea0e334feb add back ipv6 broadcast 2020-10-21 08:17:39 -07:00
Zack de03a5167a
Merge pull request #292 from nkhang/chore/cleanup
cleanup: cleanup dependencies and remove unused code
2020-10-21 08:16:52 -07:00
Khang. Nguyen Khac Nguyen 12e09020d1 chore(mod): cleanup dependencies
+ cleanup dependencies since we do not use spinner anymore.
2020-10-21 15:56:28 +07:00
Khang. Nguyen Khac Nguyen e85ac9f8bf chore(croc): remove redundant code
+ remove redundant return of func that does not return
+ remove func that is not used
2020-10-21 15:52:04 +07:00
Khang. Nguyen Khac Nguyen 9f54f2d08f chore(comm): cleanup comm Write func
+ better handling error.
+ use Send instead of Write since we do not need number of bytes sent.
2020-10-21 15:16:42 +07:00
Zack Scholl f5624007c8 bump 8.5.2 2020-10-19 11:04:43 -07:00
Zack Scholl 9b6c33c300 bump 8.5.2 2020-10-19 11:04:42 -07:00
Zack Scholl b66cfb4cc1 disable ipv6 for peer-to-peer discovery since it causes issues 2020-10-19 11:02:48 -07:00
Zack Scholl a5bcf382e0 update deps 2020-10-19 09:45:49 -07:00
Zack Scholl 539d66806a bump 8.5.1 2020-10-13 15:48:43 -07:00
Zack Scholl 768f3e1318 bump 8.5.1 2020-10-13 15:48:43 -07:00
Zack Scholl a968f494fa better help 2020-10-13 15:47:53 -07:00
Zack Scholl 911bb22b2d better environmental variable 2020-10-13 15:47:00 -07:00
Zack Scholl 58796824bb update deps 2020-10-13 15:45:54 -07:00
Zack Scholl f3697f6aad reduce packets sent for peer discovery 2020-10-13 13:47:43 -07:00
Zack Scholl 5374be1a0f use dns to determine relay 2020-10-13 12:26:11 -07:00
Zack Scholl 1d874b5dbe bump 8.5.0 2020-10-12 12:34:47 -07:00
Zack Scholl 586fc08768 bump 8.5.0 2020-10-12 12:34:47 -07:00
Zack Scholl fa1359f1b8 dos2unix 2020-10-12 12:33:56 -07:00
Zack Scholl b12fc47951 update deps 2020-10-12 12:31:54 -07:00
Zack 5a2d51c060
bash continues if autocompletion fails to install
Fixes #286
2020-10-09 07:16:17 -07:00
Zack 3396743d73
allow proxying connection (#283) 2020-10-05 08:30:45 -07:00
Zack Scholl e75b75164f bump 8.4.0 2020-10-04 13:16:36 -07:00
Zack Scholl 224c442567 bump 8.4.0 2020-10-04 13:16:35 -07:00
Zack 669920d4b5
Merge pull request #281 from TheQueasle/253-autocomplete-install
First pass at adding in the autocomplete files to the installer script
2020-10-04 13:12:04 -07:00
Zack 626490545a
Merge pull request #280 from fooofei/bug/review
CodeReview: fix resource leak && shorter code
2020-10-04 08:09:06 -07:00
fooofei 5a0ec9431f fix resource leak of *os.File 2020-10-04 10:38:30 +08:00
fooofei bc8c5db898 fix possible panic of nil compressor 2020-10-04 10:38:04 +08:00
fooofei c877497cc9 user io.ReadFull for shorter connection read code 2020-10-04 10:37:36 +08:00
Micheal Quinn 4675976f08 First pass at adding in the autocomplete files to the installer script 2020-09-29 22:19:10 -05:00
Zack f484635321
Merge pull request #276 from 0mp/patch-1
Add FreeBSD installation instructions
2020-09-26 05:39:05 -07:00
Mateusz Piotrowski d0f3bad818
Add FreeBSD installation instructions 2020-09-26 13:01:29 +02:00
Zack 4e6efc2678
Merge pull request #273 from abdulniyaspm/typo-fix
Fixed a typo in cli.go
2020-09-23 05:33:23 -07:00
ABDUL NIYAS P M 4ce170e73d
Fix a typo in cli.go 2020-09-23 16:28:00 +05:30
Zack 04e92a4ccd
Merge pull request #271 from tuxuser/readme/gentoo_portage
README: Add install instructions for gentoo via portage
2020-09-21 06:12:51 -07:00
Zack Scholl 43d2ff0a09 find open ports to open local relay 2020-09-21 06:02:13 -07:00
Zack Scholl 78e4d5e179 add util to find open ports 2020-09-21 05:51:50 -07:00
tuxuser 3d0b5b9d34 README: Add install instructions for gentoo via portage 2020-09-21 03:16:15 +02:00
Zack dab52b4af7
Merge pull request #268 from theStack/fix_send_without_argument
fix send without argument (trigger intended error message)
2020-09-20 15:32:34 -07:00
Sebastian Falbesoner a313a96a8e fix send without argument (trigger intended error message) 2020-09-19 21:48:11 +02:00
Zack a507b98cbe
Merge pull request #266 from theStack/show_all_files_when_sending_without_send
Show all files when sending without send command
2020-09-19 09:35:14 -07:00
Sebastian Falbesoner 2de73cb138 show all files when sending without send command 2020-09-19 17:52:32 +02:00
Zack 20a8603ffe
Merge pull request #265 from TheChiefMeat/patch-1
Added Chocolatey installation information
2020-09-19 06:53:24 -07:00
TheChiefMeat ebe713e881
Added Chocolatey installation information 2020-09-19 12:35:35 +01:00
Zack 28c38a4b9e
doh 2020-09-18 17:07:55 -07:00
Zack 1faebcf2e2
Fixes #262 2020-09-18 17:07:41 -07:00
Zack db388f47a6
Merge pull request #263 from sa3dany/patch-1
fix typo in readme
2020-09-18 10:58:31 -07:00
sa3dany a0cc9e943b
fix typo in readme 2020-09-18 20:42:34 +03:00
Zack Scholl 9ac64f5c75 fast 2020-09-18 06:38:18 -07:00
Zack Scholl 7b15dcd2dc fork urfave/cli 2020-09-17 13:04:33 -07:00
Zack Scholl fda0bf7fd4 bump 8.3.2 2020-09-16 14:54:02 -07:00
Zack Scholl 7d155adcf1 bump 8.3.2 2020-09-16 14:54:02 -07:00
Zack Scholl ebc2cb2d03 update progressbar and peerdiscovery 2020-09-16 14:28:11 -07:00
Zack b144fa28e7
Merge pull request #260 from masterZSH/master
Use hex.EncodeToString to encode to hex
2020-09-16 11:00:09 -07:00
masterZSH f9f32a4b0e Use hex.EncodeToString to encode to hex 2020-09-16 16:37:21 +08:00
Zack Scholl b916b89f7e include files as they are 2020-09-15 12:46:42 -07:00
Zack Scholl 32bb98fd4f fix making publish 2020-09-15 12:46:07 -07:00
Zack Scholl ad6e7dff43 add autocomplete files to goreleaser 2020-09-15 12:30:53 -07:00
Zack Scholl a48bf7bbe0 hook happens in make file 2020-09-15 12:29:36 -07:00
Zack de8dfb10aa
Merge pull request #259 from masterZSH/master
Add error reporting
2020-09-15 09:23:42 -07:00
masterZSH 833668e8f2 Add error reporting 2020-09-15 09:33:43 +08:00
Zack Scholl 8a0800ca90 better error 2020-09-13 12:15:05 -07:00
Zack Scholl 4fc40274db use default bash complete 2020-09-13 12:11:18 -07:00
Zack Scholl 8c116cf66a add autocompletion 2020-09-12 08:42:19 -07:00
Zack acda80d35c
Merge pull request #254 from Naramsim/patch-1
docs(readme): shorten docker command for the relay
2020-09-09 13:18:12 -07:00
Alessandro Pezzè 1534e913a3
docs(readme): shorten docker command for the relay 2020-09-09 21:53:15 +02:00
Zack b9e834104a
Merge pull request #252 from jolheiser/env
Add environment variables to CLI
2020-09-09 09:35:07 -07:00
Zack 0aabd23c61
Merge pull request #251 from jolheiser/gitignore
Simple gitignore
2020-09-09 09:34:27 -07:00
jolheiser ccba416e85
Env vars for a few CLI options
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2020-09-09 10:25:13 -05:00
jolheiser 8258222cc5
Simple gitignore
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2020-09-09 10:22:53 -05:00
Zack f70eb17afb
Merge pull request #249 from jolheiser/cli
Update CLI to v2
2020-09-09 08:12:25 -07:00
jolheiser 5ad8bd8e2c
Fix aliases
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2020-09-09 10:06:13 -05:00
jolheiser 9a20d507a7
Update CLI to v2
Signed-off-by: jolheiser <john.olheiser@gmail.com>
2020-09-09 10:05:57 -05:00
Zack f2c5ca820a
Merge pull request #246 from herbygillot/readme-macports
README: add instructions for installing with MacPorts
2020-09-07 22:16:38 -07:00
Herby Gillot ce7c497c09 README: add instructions for installing with MacPorts 2020-09-08 00:15:07 -04:00
Zack 1226a802e4
Merge pull request #244 from astrophena/patch-1
Add Termux installation instructions to README.md
2020-09-06 15:42:49 -07:00
Ilya Mateyko f20c42319b
Add Termux installation instructions to README.md 2020-09-07 01:03:24 +03:00
Zack Scholl a5e882ec25 bump 8.3.1 2020-09-06 08:47:32 -07:00
Zack Scholl 9d5302b1b7 bump 8.3.1 2020-09-06 08:47:31 -07:00
Zack Scholl bdb859c15c use version 2020-09-06 08:45:59 -07:00
Zack Scholl 22c35412ac bump 8.3.1 2020-09-06 08:44:04 -07:00
Zack Scholl f2af0b7ed5 bump 8.3.1 2020-09-06 08:44:03 -07:00
Zack Scholl 5d6546ba58 tag 2020-09-06 08:43:14 -07:00
Zack Scholl f4fe211bbe bump 8.3.2 2020-09-06 08:42:51 -07:00
Zack Scholl f950633a86 bump 8.3.2 2020-09-06 08:37:37 -07:00
Zack Scholl 65b6111512 push before prepare 2020-09-06 08:37:10 -07:00
Zack Scholl 2db2a914f2 bump 8.3.1 2020-09-06 08:33:14 -07:00
Zack Scholl 345ef0567e compute filename and deliver without overwriting 2020-09-05 17:23:07 -07:00
Zack 189890259e
Update README.md 2020-09-04 09:00:30 -07:00
Zack Scholl e771e20ac4 fix version 2020-09-04 06:08:38 -07:00
Zack Scholl 5e78725afa Fixes #240 2020-09-04 06:06:48 -07:00
Zack Scholl fc14ef25ed version with v 2020-09-03 15:55:52 -07:00
Zack Scholl b48c96fc37 bump 8.3.0 2020-09-03 15:51:13 -07:00
Zack Scholl 87e54acd8a add option to disable compression Fixes #239 2020-09-03 15:09:23 -07:00
Zack Scholl 555ddec5e3 handle symlinks Fix #238 2020-09-03 14:57:09 -07:00
Zack Scholl ff99b07ef1 gather symlink info 2020-09-03 14:49:08 -07:00
Zack Scholl 26056a8366 test release 2020-09-03 14:21:43 -07:00
Zack Scholl 3692e32dfb don't tag version before commiting 2020-09-03 14:19:32 -07:00
Zack Scholl 11efb6be5e get version from env varaible 2020-09-03 14:17:12 -07:00
Zack Scholl 900424ca66 update go in docker 2020-09-03 13:34:10 -07:00
Zack Scholl bd2376e920 allow getting password through file Fix #226 2020-09-03 13:31:01 -07:00
Zack Scholl def4f94ffd Merge branch 'master' of github.com:schollz/croc into master 2020-09-03 12:45:47 -07:00
Zack Scholl bbc0ce4e9c better info about incorrect passwords Fixes 237 2020-09-03 12:45:40 -07:00
Zack Scholl 8b6c0d1c39 bump 8.2.1 2020-09-03 11:40:29 -07:00
Zack Scholl d55327d344 bump 8.2.1 2020-09-03 11:40:23 -07:00
Zack Scholl c7ba55fc83 use default port of 9009 if none found #236 2020-09-03 09:53:14 -07:00
Zack Scholl 85b370291d update readme about sending text Fixes #233 2020-09-03 09:42:56 -07:00
Zack Scholl 81ad30c633 bump 8.2.0 2020-09-02 17:37:17 -07:00
Zack ba2c46c1cb
Merge pull request #234 from schollz/text
send and receive text
2020-09-02 17:36:33 -07:00
Zack Scholl 0eb095bf76 println 2020-09-02 17:35:36 -07:00
Zack Scholl 8fbb7e5019 send and receive text 2020-09-02 17:33:53 -07:00
Zack Scholl 48d63e4854 text works 2020-09-02 17:24:32 -07:00
Zack Scholl ea781e569b bug fix: propogate error when connecting 2020-09-02 09:46:31 -07:00
Zack Scholl a8c5bef7c0 raise max bytes to allow huge files #231 2020-09-01 09:32:03 -07:00
Zack Scholl b188a2691e bump 8.1.3 2020-08-31 11:58:07 -07:00
Zack Scholl 20967519fd update deps 2020-08-31 11:56:25 -07:00
Zack Scholl 09a37a2be4 update readme 2020-08-30 08:54:07 -07:00
Zack Scholl 7bc9dc1826 bump 8.1.2 2020-08-27 10:49:30 -07:00
Zack Scholl 2345148fde make sure conn is not nil 2020-08-27 10:13:47 -07:00
Zack Scholl 50bf003022 try ipv6 first 2020-08-27 09:40:41 -07:00
Zack Scholl 695444159e add default ipv6 relay 2020-08-27 09:24:19 -07:00
Zack Scholl 0533f0c96e release auto 2020-08-27 08:15:01 -07:00
Zack Scholl 52182099eb bump 8.1.1 2020-08-27 08:13:07 -07:00
Zack Scholl e250eeede6 add makefile for releases 2020-08-27 08:12:47 -07:00
Zack Scholl 4aa7f05630 slightly more debugging 2020-08-27 08:10:44 -07:00
Zack Scholl 3a805f8be3 bump 8.1.0 2020-08-26 19:16:25 -07:00
Zack Scholl 588e650d80 don't split host if localhost 2020-08-26 17:46:35 -07:00
Zack Scholl baddb93c4e local ipv6 works 2020-08-26 14:56:57 -07:00
Zack Scholl c9a58513e1 attempt to use ipv6 discoveries 2020-08-26 14:42:49 -07:00
Zack Scholl 8f13aedc19 thanks 2020-08-26 10:00:56 -07:00
Zack Scholl c0a05401c9 update deps 2020-08-26 09:58:06 -07:00
Zack Scholl ae384490d6 don't create folder if its a . 2020-08-26 09:55:59 -07:00
Zack e3ed4ba998
Merge pull request #228 from lpar/cleanup
Improve error reporting
2020-08-26 09:50:24 -07:00
Zack 43480dd997
Merge pull request #227 from lpar/master
Initial IPv6 fixes
2020-08-26 09:49:16 -07:00
mathew 6874d9eede Improve error reporting 2020-08-22 18:12:09 -05:00
mathew 1b646d5528 Improve error reporting 2020-08-22 18:05:00 -05:00
mathew 827b5d3a86 Initial IPv6 fixes 2020-08-22 14:51:32 -05:00
Zack Scholl 0beeebc351 bump 8.0.13 2020-08-12 09:59:07 -07:00
Zack Scholl f4047d5500 remove snap 2020-08-12 09:59:00 -07:00
Zack Scholl 4deced8827 bump 8.0.13 2020-08-12 09:58:13 -07:00
Zack Scholl c260147714 ignore darwin386 2020-08-12 09:58:11 -07:00
Zack Scholl 81e9f772a1 bump 8.0.13 2020-08-12 09:57:18 -07:00
Zack Scholl 8b11c5b661 ignore darwin386 2020-08-12 09:57:06 -07:00
Zack Scholl 009f36f16c bump 8.0.13 2020-08-12 09:49:29 -07:00
Zack Scholl 73dec72a74 update deps 2020-08-12 09:49:06 -07:00
Zack Scholl ee9188b082
signed commit 2020-07-17 12:54:10 -07:00
Zack Scholl fdf383b2d7 bump 8.0.12 2020-07-15 10:48:52 -07:00
Zack Scholl 7fd8fda107 default to port 9009 if port is lost during discovery
fixes #222
2020-07-15 10:47:56 -07:00
Zack Scholl 1255a79a57 update deps 2020-07-14 15:34:57 -07:00
Zack Scholl b4e1ed2697 update deps 2020-06-19 13:23:32 -07:00
Zack Scholl 0377223a67 fix tests: generate file in reproducible way #218 2020-05-18 07:20:51 -07:00
Zack dd9cd82732
Create FUNDING.yml 2020-05-13 14:08:02 -07:00
Zack 91468709aa
update readme with number of ports for relay 2020-05-12 12:04:08 -07:00
Zack Scholl 23c21bcafd bump 8.0.11 2020-05-12 11:33:03 -07:00
Zack Scholl 78b643792e revert 2020-05-12 11:30:00 -07:00
Zack Scholl 532cfa9cd9 bump 8.0.11 2020-05-12 05:41:57 -07:00
Zack Scholl cf6b13d156 add personal files to plugs #190 2020-05-12 12:39:15 +00:00
Zack 9440d8eb04
add gif 2020-05-08 11:00:07 -07:00
Zack Scholl 14f6a4a8be add example gif 2020-05-08 10:58:51 -07:00
Zack Scholl 93e45c6942 bump 8.0.10 2020-05-06 10:55:14 -07:00
Zack Scholl 6dc44ec002 faster pake 2020-05-06 10:50:57 -07:00
Zack Scholl 4211cea92e add benchmark for tcp connection 2020-05-06 10:18:39 -07:00
Zack Scholl 1740bda985 bump 8.0.9 2020-05-01 07:00:17 -07:00
Zack Scholl 189d1f7b2a update deps 2020-05-01 06:59:09 -07:00
Zack Scholl 86ebbaa618 bump 8.0.8 2020-04-24 08:17:24 -07:00
Zack Scholl 2e7708e3cd whoops 2020-04-22 07:08:08 -07:00
Zack Scholl cb522f2f06 debugging the comm 2020-04-22 06:24:47 -07:00
Zack Scholl 97f7f28f6e update deps 2020-04-20 12:33:16 -07:00
Zack Scholl 3ed036b51d bug fix: increase deadline for reading in channels, addresses #211 2020-04-20 12:30:07 -07:00
Zack Scholl a3e81e1d87 bump 8.0.7 2020-04-09 10:12:30 -07:00
Zack Scholl e56e65207f bump 8.0.7 2020-04-09 09:55:36 -07:00
Zack Scholl f6ea7243ea update readme 2020-04-09 09:54:58 -07:00
Zack Scholl f9f4f291da use debug instead of warn/error addresses #205 2020-04-09 09:54:04 -07:00
Zack d1c2777906
Merge pull request #209 from maximbaz/relay-show-version-on-startup
relay: show version on startup
2020-04-09 09:50:21 -07:00
Zack 0860283407
Merge pull request #210 from maximbaz/add-systemd-service
Add systemd service
2020-04-09 09:49:55 -07:00
Maxim Baz cb025ae8d4
Add systemd service
A while ago a user contributed this systemd service to Arch package, I thought it would make sense to have it available in the repo itself, so that (a) other people can find it easier and (b) if there are any improvements, the entire community will benefit of them.
2020-04-09 18:14:00 +02:00
Maxim Baz c058bcbb6b
relay: show version on startup
Since relay is a long-running process, I find myself in situations where I dont know which version of croc I have running.

This simple startup log will make it obvious.
2020-04-09 17:44:19 +02:00
Zack Scholl 9bf470ef29 bump 8.0.6 2020-04-09 08:02:10 -07:00
Zack Scholl 11d4fead2c update deps 2020-04-09 08:01:20 -07:00
Zack Scholl 9c0bc3efc3 bug fix: two read deadlines to prevent memory leak
addresses #205
2020-04-09 07:40:39 -07:00
Zack Scholl 386f4ff958 bump 8.0.5 2020-03-31 13:43:13 -07:00
Zack Scholl 97bf35bf93 fix debug 2020-03-31 13:42:52 -07:00
Zack Scholl f8fd239eec bump 8.0.5 2020-03-31 13:34:10 -07:00
Zack Scholl 72378947b5 update progressbar, show external ip on receiver 2020-03-31 13:33:27 -07:00
Zack Scholl b0125b63e7 test should not exceed max bytes 2020-03-27 09:38:09 -07:00
Zack Scholl b60a841044 bug fix: prevent crazy number of bytes getting into comm 2020-03-27 09:32:41 -07:00
Zack Scholl 44c3d43fa0 bump 8.0.4 2020-03-24 08:37:14 -07:00
Zack Scholl 7a605dd5c8 update deps 2020-03-24 08:36:52 -07:00
Zack Scholl aae56043cf bug fix: lock the chunk map
addresses #204
2020-03-18 03:06:50 +00:00
Zack Scholl 09d35d248f bump 8.0.3 2020-03-08 07:15:32 -07:00
Zack Scholl 03fe1c770a bump 8.0.2 2020-03-06 07:15:04 -08:00
Zack Scholl 1dd75c4bc3 better error messages 2020-03-06 07:12:08 -08:00
Zack Scholl 8b6500adfd hide most of the code phrase to use as authentication 2020-03-06 07:05:04 -08:00
Zack Scholl 3cf474e6e8 more tests 2020-03-02 10:10:17 -08:00
Zack Scholl 820225b684 more tests 2020-03-02 10:06:20 -08:00
Zack Scholl eddf361893 bump 8.0.1 2020-03-02 09:42:34 -08:00
Zack Scholl 2d6206b84f bump 8.0.1 2020-03-02 09:35:35 -08:00
Zack Scholl 074a869d6e bump 8.0.0 2020-03-02 09:04:25 -08:00
Zack 0c305fee08
Merge pull request #201 from schollz/v8
V8
2020-03-02 09:03:28 -08:00
Zack Scholl 5e37a308fe throw error when submitting bad passphrase to relay 2020-02-28 17:05:03 -08:00
Zack Scholl bc1f89ff68 bump 8.0.0 2020-02-28 16:57:46 -08:00
Zack Scholl 788a63cfa6 update deps 2020-02-28 13:31:04 -08:00
Zack Scholl a87b571376 update dockerifle 2020-02-28 13:30:39 -08:00
Zack Scholl 0b99be5b30 update year 2020-02-28 13:27:44 -08:00
Zack Scholl c3adc2981f encrypt external ip 2020-02-28 13:02:23 -08:00
Zack Scholl 5fce2a2e27 encrypt external ip 2020-02-28 12:58:46 -08:00
Zack Scholl d5846bc88d encrypt all communication with relay 2020-02-28 11:59:56 -08:00
Zack 2217f7ca61
Thanks! 2020-02-18 11:44:15 -08:00
Zack Scholl 4c56ec283d bump 6.4.11 2020-02-18 11:28:36 -08:00
Zack Scholl bc0841d8a1 update deps 2020-02-18 11:25:02 -08:00
Zack d4cbe03d0d
Merge pull request #198 from rkuprov/shared-secret-update
croc: secret phrase parsing
2020-02-18 10:51:29 -08:00
Roman df79b2ed8e croc: secret phrase parsing
what:
- `croc alpha beta gamma` is now properly understood as
 `croc alpha-beta-gamma`.

why:
- to increase convenience.
2020-02-17 21:31:56 -07:00
Zack Scholl 29882db39b bump 6.4.10 2020-01-15 09:14:37 -08:00
Zack Scholl 073569f292 need to add network bind to snap 2020-01-15 09:14:06 -08:00
Zack Scholl d6694a9b41 bump 6.4.9 2020-01-15 08:07:22 -08:00
Zack Scholl 5369fbc3aa bump 6.4.9 2020-01-15 08:06:28 -08:00
Zack Scholl 03d9785408 update deps, add snapcraft plugs 2020-01-15 08:06:08 -08:00
Zack Scholl fbcad738bb bump 6.4.8 2019-12-23 14:49:22 -08:00
Zack Scholl fd20b25a30 update deps 2019-12-23 14:48:44 -08:00
Zack Scholl aa54ff18e5 add snap install directions 2019-12-23 07:57:44 -08:00
Zack Scholl 44286ce473 thanks! 2019-12-23 07:56:44 -08:00
Zack Scholl 4824033619 clearly specify password 2019-12-23 07:55:10 -08:00
Zack 493ae9306d
Merge pull request #185 from xenrox/docker-pass-support
Support relay password for docker
2019-12-23 07:53:04 -08:00
Zack Scholl 25902edf5b bump 6.4.7 2019-12-16 07:38:56 -08:00
Zack Scholl 3d9bbff7a7 bump 6.4.7 2019-12-16 07:38:18 -08:00
Zack Scholl 02be7abe32 bump 6.4.7 2019-12-16 07:37:57 -08:00
Zack Scholl 4dd2922b5f fix snapcraft 2019-12-16 07:37:30 -08:00
Thorben Günther 06dd3ba62f
Don't force users to set $CROC_PASS 2019-12-07 02:06:01 +01:00
Thorben Günther 1ae85758f0
Support relay password for docker 2019-12-06 12:31:26 +01:00
Zack f12940bbcd
Merge pull request #183 from TheQueasle/fresh-mac-path-missing
Adding a function that creates the prefix
2019-11-26 12:50:33 -08:00
Micheal Quinn 247a698757 Adding in EUID check to create_prefix. Also adding in more checks to that function to make sure the tools needed are available. 2019-11-26 14:18:30 -06:00
Micheal Quinn 47d84b9947 Adding rcode for completness sake on the create_prefix function. 2019-11-26 13:50:31 -06:00
Micheal Quinn f6ad8f57cf Adding a function that creates a prefix and logic surrounding it to only create it if it does not already exist 2019-11-26 13:41:38 -06:00
Zack 24cb8f0103
Update README.md 2019-11-26 09:50:16 -08:00
Zack Scholl f52447acd9 bump 6.4.6 2019-11-21 15:24:25 -08:00
Zack Scholl 3c03719863 need to close goroutine corrrectly 2019-11-21 15:10:21 -08:00
Zack Scholl 5bafc99741 check if the purported IP is really local #168 2019-11-21 14:58:48 -08:00
Zack Scholl 20061b484e bump 6.4.5 2019-11-19 16:39:38 -08:00
Zack 88c4257816
Merge pull request #180 from maximbaz/support-default-port-receiver
Support default port on receiver side
2019-11-19 16:38:40 -08:00
Maxim Baz 1a544e4624
Support default port on receiver side 2019-11-20 01:11:52 +01:00
Zack Scholl eb85477086 bump 6.4.4 2019-11-19 15:25:33 -08:00
Zack Scholl 5faacd3328 try 9009 port by default #178 2019-11-19 15:19:53 -08:00
Zack 04cad7b9a5
thanks! 2019-11-19 14:05:05 -08:00
Zack Scholl 60d6489c69 bump 6.4.3 2019-11-19 14:01:57 -08:00
Zack 0e555179f8
Merge pull request #176 from maximbaz/patch-2
Add version to the dir name in the source tarball
2019-11-19 14:01:20 -08:00
Zack 3d672d6ac2
Merge pull request #179 from maximbaz/remember-relay-password-receive
Remember relay password on receive too #177
2019-11-19 14:00:34 -08:00
Maxim Baz b27b814b49
Switch to GlobalIsSet 2019-11-19 22:58:35 +01:00
Maxim Baz cc6af6e5e8
Checkout the version tag when cloning repo 2019-11-19 22:57:24 +01:00
Maxim Baz 252475f72e
Remember relay password on receive too #177 2019-11-19 21:06:12 +01:00
Zack Scholl e3ba938582 set relay password when remembering #177 2019-11-19 11:47:04 -08:00
Maxim Baz 1cdccfa884
Add version to the dir name in the source tarball 2019-11-19 19:38:29 +01:00
Zack Scholl e84e89b786 bump 6.4.2 2019-11-19 10:15:44 -08:00
Zack Scholl fb35da42ed upload separately 2019-11-19 10:15:02 -08:00
Zack Scholl d91ce7e469 bump 6.4.2 2019-11-19 10:12:18 -08:00
Zack Scholl cbc55a84a7 add snapcraft back 2019-11-19 10:12:07 -08:00
Zack Scholl 0694d61294 add upload asset to goreleaser #172 2019-11-19 09:24:13 -08:00
Zack f102195354
Merge pull request #175 from apeyrat/master
croc is now available in the main scoop bucket
2019-11-19 07:05:29 -08:00
Alain a5571306c2
croc is now available in the main bucket
No need to add dedicated channel as it is available in the main bucket.
See: https://github.com/ScoopInstaller/Main/blob/master/bucket/croc.json
2019-11-19 13:24:54 +01:00
Zack Scholl 60030cdfbb bump 6.4.1 2019-11-18 14:31:29 -08:00
Zack Scholl 181dee9991 quit on bad password 2019-11-18 14:26:01 -08:00
Zack Scholl bcb2b5d783 fix tests 2019-11-18 13:27:22 -08:00
Zack Scholl af95cddd8d fix tests 2019-11-18 13:25:51 -08:00
Zack Scholl 6b26af4dca bump 6.4.0 2019-11-18 13:15:51 -08:00
Zack Scholl b9b3995f02 exit on EOF 2019-11-18 13:15:41 -08:00
Zack Scholl d0c2dc1be8 use one-byte pings 2019-11-18 13:09:17 -08:00
Zack 544d3e0144 Update issue templates 2019-11-18 12:07:35 -08:00
Zack Scholl c369f67745 fix src bundle 2019-11-18 12:02:54 -08:00
Zack Scholl 76fc3f1a77 fix tests 2019-11-18 11:13:36 -08:00
Zack Scholl baf5d6f27f bump 6.3.0 2019-11-18 10:43:28 -08:00
Zack Scholl 497ffb8c2f update deps 2019-11-18 10:43:14 -08:00
Zack Scholl 7b5acc89a4 remove snapcraft for now 2019-11-18 10:42:42 -08:00
Zack Scholl eb22400db0 bump 6.3.0 2019-11-18 10:23:29 -08:00
Zack Scholl 79e5f4445b fix goreleaser 2019-11-18 10:23:27 -08:00
Zack Scholl 0f15698970 bump 6.3.0 2019-11-18 10:21:13 -08:00
Zack Scholl 419a766c6f fix goreleaser 2019-11-18 10:21:10 -08:00
Zack Scholl 19b5923f48 bump 6.3.0 2019-11-18 10:20:29 -08:00
Zack Scholl 2f2e19aa91 add snap to croc 2019-11-18 10:15:57 -08:00
Zack Scholl ae412375ef Merge branch 'master' of github.com:schollz/croc 2019-11-18 08:18:37 -08:00
Zack Scholl 21c1efe319 fix tests 2019-11-18 08:18:30 -08:00
Zack 4206605a2d
Merge pull request #174 from schollz/pass
implement password addresses #173
2019-11-18 08:17:03 -08:00
Zack Scholl 9d5eec4246 implement password addresses #173 2019-11-18 08:16:19 -08:00
Zack Scholl 3941762bf3 allow disabling multiplexing 2019-11-18 07:57:12 -08:00
Zack Scholl 648c41d707 use siec 2019-11-18 07:53:57 -08:00
Zack Scholl c7f419ca2d use functional encryption 2019-11-18 07:50:43 -08:00
Zack Scholl fe8dad42f7 bump 6.2.4 2019-11-18 07:42:09 -08:00
Zack Scholl 6a036d68f6 update releaser 2019-11-18 07:36:49 -08:00
rain1 b755d3f827 Update README.md
remove link to release
2019-11-18 07:36:49 -08:00
rain1 25776a1d96 Update README.md 2019-11-18 07:36:49 -08:00
rain1 9ec23ae367 Update README.md
remove curl | bash recommendation
2019-11-18 07:36:49 -08:00
Zack 43927a6dbb
Merge pull request #152 from HugoReeves/master
readme: add nix install instructions
2019-11-17 13:23:55 -08:00
Zack Scholl b8bcbb3ecc bump 6.2.3 2019-11-17 13:20:45 -08:00
Zack Scholl b7625ef55c add more info on how to send 2019-11-17 13:19:27 -08:00
Zack Scholl b7565177be fix tests 2019-11-17 13:05:43 -08:00
Zack Scholl a7aed67c65 bump 6.2.2 2019-11-17 13:00:41 -08:00
Zack Scholl b4f8fafb63 don't hang it no acceptance
Fixes #171
2019-11-17 12:59:29 -08:00
Zack Scholl 04724f4900 bump 6.2.1 2019-11-17 09:44:02 -08:00
Zack Scholl b2e81fb50d update deps 2019-11-17 09:41:50 -08:00
Zack 1754333ac0
Merge pull request #170 from maximbaz/patch-1
Add Arch Linux installation to README
2019-11-13 08:15:21 -08:00
Maxim Baz f3799213b6
Add Arch Linux installation to README 2019-11-13 01:41:41 +01:00
Zack bfa7768781
Update README.md 2019-11-12 12:14:42 -08:00
Zack Scholl acd7d8d8ec add profiling lines 2019-11-11 11:26:32 -08:00
Zack Scholl bdb8bf3ac4 addresing CPU usage #168 2019-11-11 11:26:12 -08:00
Zack a0d9d74d5d
Merge pull request #166 from taigrr/master
Update README.md
2019-11-03 17:18:39 -07:00
Tai Groot 68f039fbb0
Update README.md
Removed v6 that causes error from build from source instructions
2019-11-03 16:09:07 -08:00
Zack 9afae3b6b0
Merge pull request #164 from schollz/prepend
Prepend payload with 'croc' so no interference from other broadcasts
2019-10-28 13:15:47 -07:00
Zack Scholl c7624535e9 skip discovery 2019-10-28 13:13:03 -07:00
Zack Scholl da626334e0 check discoveries for right prefix 2019-10-28 12:46:24 -07:00
Zack Scholl aaeda77af4 bump 6.2.0 2019-10-24 07:22:57 -07:00
Zack Scholl ffddd3e989 prompt if sender wants to ask 2019-10-24 06:58:12 -07:00
Zack 4b8d32ff75
Merge pull request #161 from schollz/ask
ask using the machine ID for extra secure layer Fixes #159
2019-10-23 15:01:55 -07:00
Zack Scholl 9aa327a0a4 use machine ID 2019-10-23 14:59:47 -07:00
Zack Scholl 42c2d5c6c1 add ask flag 2019-10-23 14:07:52 -07:00
Zack 41b91a3baf
Merge pull request #157 from TheQueasle/centos8_support
Adding in a more detailed error message for when an extraction tool is not found.
2019-10-09 09:45:08 -07:00
Micheal Quinn 183791d4c4
Adding in a more detailed error message for when an extraction tool is not found in PATH. CentOS 8 Minimal install seems to not include tar... 2019-10-08 22:49:32 -05:00
Zack c4d8c168a3
Update .travis.yml 2019-10-08 16:35:11 -07:00
Zack Scholl e286321d39 bump 6.1.5 2019-10-07 16:22:58 -07:00
Zack Scholl af39b8ca14 pad filenames according to longest filename 2019-10-07 16:20:24 -07:00
Zack 810a04509a
Update .travis.yml 2019-10-03 13:00:00 -07:00
Zack Scholl 59666c564d bump 6.1.4 2019-10-03 12:09:18 -07:00
Zack Scholl 00e6ac9316 bump 6.1.4 2019-10-03 12:08:18 -07:00
Zack Scholl 7a1fb8db24 update deps 2019-10-03 12:07:45 -07:00
Zack Scholl 5d89bdb6f9 reduce complexity 2019-09-20 10:06:50 -07:00
Zack Scholl c46a9d3ae0 reduce complexity 2019-09-20 10:06:26 -07:00
Zack Scholl ae81dd9a7b reduce complexity 2019-09-20 10:05:29 -07:00
Zack Scholl 4e94a22300 reduce complexity 2019-09-20 10:03:06 -07:00
Zack Scholl 8be63bed43 reduce complexity 2019-09-20 10:00:52 -07:00
Zack Scholl a7435a08bd reduce complexity 2019-09-20 09:59:24 -07:00
Zack Scholl 22ead388cd reduce complexity 2019-09-20 09:57:18 -07:00
Zack Scholl 7ac7e5d56d reduce complexity 2019-09-20 09:54:10 -07:00
Zack Scholl cfbd65be31 reduce complexity 2019-09-20 09:47:47 -07:00
Zack Scholl 07c20e2cde reduce complexity 2019-09-20 09:45:42 -07:00
Zack Scholl 24abf4fdd8 reduce complexity 2019-09-20 09:43:16 -07:00
Zack Scholl 768ad9b739 reduce complexity 2019-09-20 09:41:58 -07:00
Zack Scholl 6202d0d932 reduce complexity 2019-09-20 09:32:32 -07:00
Zack Scholl 049a4aaffc reduce complexity 2019-09-20 09:27:59 -07:00
Zack Scholl 1fe8ccf3ab reduce complexity 2019-09-20 09:24:10 -07:00
Zack Scholl 9fb54a3952 reduce complexity 2019-09-20 09:20:50 -07:00
Zack a0e2876741
Merge pull request #153 from TheQueasle/install_script_rewrite
Install script rewrite
2019-09-10 07:41:07 -07:00
Micheal Quinn 932f037b17
Moving the new script back into place. I think the merge conflict is resolved now. 2019-09-10 07:31:13 -05:00
Micheal Quinn fe4e9c357a
Upping version of croc in the installer script. 2019-09-10 07:30:31 -05:00
Micheal Quinn c0f7c3c250
Merge branch 'master' of https://github.com/schollz/croc into install_script_rewrite 2019-09-10 07:29:24 -05:00
Micheal Quinn f01165e9f4
Trying to get out of this merge confilct 2019-09-10 07:29:17 -05:00
Micheal Quinn 5fbb787a84
Adding in message and exit for cygwin. 2019-09-10 07:20:39 -05:00
Zack Scholl 24801dfc24 coverage improved 2019-09-08 06:14:33 -07:00
Zack Scholl 5ad631e7b6 add more tests 2019-09-08 06:12:16 -07:00
Zack Scholl cc728a1138 fix minor bug 2019-09-08 06:07:53 -07:00
Zack Scholl b979607c42 fix 2019-09-08 05:56:57 -07:00
Zack Scholl f89dd01e87 add more tests 2019-09-08 05:53:30 -07:00
Zack Scholl 6287a7b7f7 add coveralls link 2019-09-07 10:40:30 -07:00
Zack Scholl 22f6a13a9f add more tests 2019-09-07 10:31:18 -07:00
Zack Scholl a82dd2f284 improve tests 2019-09-07 10:06:41 -07:00
Zack Scholl 33aa006c26 fix spelling 2019-09-07 09:49:08 -07:00
Zack Scholl 845dabbae0 Merge branch 'master' of github.com:schollz/croc 2019-09-07 09:46:08 -07:00
Zack Scholl 31c1a37b38 fix linting 2019-09-07 09:46:04 -07:00
Zack Scholl 0277abe5d4 gofmt -s -w 2019-09-07 09:41:24 -07:00
Zack 175b9a3f76
Update README.md 2019-09-07 08:18:21 -07:00
Zack Scholl 9a70ea90d1 bump 6.1.3 2019-09-07 07:41:03 -07:00
Zack bc6803eeef
use single reader (#155)
* dunno

* close file after finished

* fix debugging statements

* use single reader

* update deps
2019-09-07 07:34:05 -07:00
Zack Scholl fb658ccde2 update deps 2019-09-04 09:00:29 -07:00
Zack Scholl de7a29470b bump 6.1.2 2019-08-27 17:11:58 -07:00
Zack Scholl 4150feddf0 skip checking each file each time 2019-08-27 09:51:37 -07:00
Micheal Quinn 97f65bf51d
Adding in stdout of checksum check if the check fails 2019-08-23 11:50:40 -05:00
Micheal Quinn 07a2abd808
Adding in a banner...because all the cool kids are doing it. 2019-08-23 11:05:57 -05:00
Zack Scholl 7515c92a8b update deps 2019-08-22 13:22:31 -07:00
Micheal Quinn 7a6c4db5f9
Moving new file to default.txt. Removed todo (will be recreated in the pull request to come) 2019-08-21 22:47:51 -05:00
Micheal Quinn e3e7ada3e6
Updating todo 2019-08-15 20:50:33 -05:00
Micheal Quinn 105357bcbf
Updating todo 2019-08-15 20:49:30 -05:00
Micheal Quinn d6d96e487f
fixing returncode for download_file 2019-08-15 20:48:46 -05:00
Micheal Quinn d3207e6190
First pass of upping rcodes for some of the functions that may have tool return codes clash. Also changing some logic for determine_os and determine_arch to make it a little more better 2019-08-15 20:06:04 -05:00
Quinn 51e77ba0c4
Update rewrite_todo.md 2019-08-14 17:07:43 -05:00
Quinn f3efbb34af
Update rewrite_todo.md 2019-08-14 17:04:21 -05:00
Quinn 9e9f43c352
Update rewrite_todo.md 2019-08-13 23:16:46 -05:00
Quinn 27bc2e8c8a
Update rewrite_todo.md 2019-08-13 23:09:13 -05:00
Quinn 559807f97d
Forgot to update the function name for cygwin 2019-08-13 22:51:06 -05:00
Quinn a31bc56c23
More Cygwin updates
Forgot to update the install logic case statement in main
2019-08-13 22:45:59 -05:00
Quinn a9caea4d64
More WIndwos (cygwin) updates
Add install_file_cygwin function to support this case
2019-08-13 22:41:48 -05:00
Quinn ec09a990af
Adding croc_dl_ext update
For when we are on a Windows/CYGWIN host
2019-08-13 22:34:40 -05:00
Micheal Quinn a72172d11e
Adding update to checksum check function to always filter the checksum file based on downloaded file. Adding CYGWIN croc_os switch for windows support (needs more testing) 2019-08-13 22:28:26 -05:00
Hugo Reeves 53328fa58b
readme: add nix install instructions 2019-08-14 11:09:13 +12:00
Quinn 081e267a19
check off bsds 2019-08-12 21:15:38 -05:00
Quinn d429e09e95
quick todo file 2019-08-12 21:15:06 -05:00
Micheal Quinn 588dfe6c00
Removing cleanup logic. rm -rf in a script terrifies me. The script attempts to place it into the temp dir, so we will let the OS clean it up. 2019-08-12 14:40:46 -05:00
Micheal Quinn e2e48d9e84
Adding in fix for macOS (Darwin) not having an install case. Uses the same logic from install_file_freebsd 2019-08-12 11:04:50 -05:00
Micheal Quinn b8d1d11b68
Changing PREFIX to INSTALL_PREFIX to avoid clashing with possibly set environment variables. Adding logic to handle if we are on termux on android (adapted from previous croc install script). Adding an info message for what prefix was set to. Adding in armv71 support (need to add more or make this a generic case to catch more arm devices). 2019-08-12 10:53:09 -05:00
Micheal Quinn 34743118de
script header cleanup 2019-08-12 09:16:24 -05:00
Micheal Quinn 9c6f01ca91
swapping getopt (which apparently is not good to use) for getopts in an attempt to make it more cross-platform without having to break out the logic based on OS...again... 2019-08-11 17:07:43 -05:00
Micheal Quinn d39266a36d
wrangling another batch of wild global vars that should be local vars 2019-08-11 16:35:51 -05:00
Micheal Quinn bf15c4c424
Adding help message formatting. Adding in sudo check. Caught and fixed some global variables that should be local. 2019-08-11 16:00:56 -05:00
Micheal Quinn 2c2920eb9c
Adding description information. Added print message function for fancy colors in the output. 2019-08-11 15:33:42 -05:00
Micheal Quinn e7d6d096a8
Adding in root check to install commands with fallback to sudo. Splitting install logic out based on host OS 2019-08-11 13:01:00 -05:00
Micheal Quinn b0ac5024a4
Adding a function to handle creation of temp dir. Polished the checksum check function to handle more cases/OSes 2019-08-11 12:31:19 -05:00
Micheal Quinn 9530952eb6
Adding install function and cleanup function 2019-08-10 21:45:53 -05:00
Micheal Quinn eaf448ddac
Adding install function and logic 2019-08-10 21:08:04 -05:00
Micheal Quinn c82dda45d9
Adding in extract file logic. 2019-08-10 18:26:06 -05:00
Micheal Quinn 7a684e7266
moving the rewrite into the proper location 2019-08-10 17:57:37 -05:00
Micheal Quinn 6178a7e16b
First pass at a rewrite. 2019-08-10 17:56:54 -05:00
Zack 02f89b1854
Merge pull request #150 from TheQueasle/freebsd_support_and_checksum_fixes
Install Script FreeBSD Support and Checksum Checks Fixes
2019-08-02 13:27:13 -07:00
Micheal Quinn d5a8d07d1c
Fixing the macos shasum call to fit into the checksum check 2019-08-02 14:37:56 -05:00
Micheal Quinn 2c27d7aabd
reverting line 147 2019-08-01 13:02:44 -05:00
Micheal Quinn f8d60c0011
Adding in some fixes for FreeBSD (tested in a FreeNAS jail 'FreeBSD 11.2-STABLE') as well as a fix for the checksum logic not correctly comparing the checksums. This still needs testing on a MacOS host 2019-08-01 12:55:05 -05:00
Zack Scholl e1e722fc5b bump 6.1.1 2019-07-20 10:01:10 -06:00
Zack Scholl 82f2c8cd2f require go1.12 2019-07-20 08:57:03 -07:00
Zack Scholl 88b4001dd7 bug fix: create directories for empty files 2019-07-20 08:55:54 -07:00
Zack Scholl 2735c42a9d send empty files 2019-07-19 17:46:02 -07:00
Zack Scholl 83db5bdc68 Merge branch 'master' of https://github.com/schollz/croc 2019-07-19 17:42:22 -07:00
Zack Scholl fe1329c909 handle if the file is zero bytes 2019-07-19 17:39:25 -07:00
Zack Scholl 336f314854 bump 6.1.0 2019-07-18 07:22:38 -06:00
Zack Scholl 6f31418330 add --remember 2019-07-18 07:22:03 -06:00
Zack bd7ab1a9be
Merge pull request #144 from schollz/config
add --remember for saving config parameters
2019-07-18 06:18:38 -07:00
Zack Scholl edc97915bd don't keep debug 2019-07-18 06:17:15 -07:00
Zack Scholl 256e0c51fa add save file for receiver 2019-07-18 06:13:11 -07:00
Zack Scholl 7fcf45cece remove unused code 2019-07-18 06:06:56 -07:00
Zack Scholl 6a8bdccb66 add receiver config 2019-07-17 18:16:50 -06:00
Zack Scholl 252e96a670 simplify toggling 2019-07-17 18:06:52 -06:00
Zack Scholl 97d18e1fbf toggling parameters 2019-07-17 17:26:42 -06:00
Zack Scholl 54fb8aec9d how to check if flag is set? 2019-07-17 17:23:50 -06:00
Zack Scholl 1d7976a61a save send remember 2019-07-17 16:19:32 -06:00
Zack Scholl f18c2eae7e add get config dir 2019-07-17 15:55:43 -06:00
Zack Scholl 68ddbe7f14 small change 2019-07-17 14:33:02 -06:00
Zack Scholl 8b178881cf display relay in UI if not using default
Fixes #143
2019-07-17 14:12:48 -06:00
Zack Scholl 9968bbf824 addressing issue #141
the local relay is not being used and then the connection is refused but it still hangs
in that case is that the sender should give up, prompting the user to try again
2019-07-17 13:04:03 -06:00
Zack Scholl 928ee1f496 bump 6.0.12 2019-07-14 20:33:47 -06:00
Zack Scholl fbbdd1bcfe update deps 2019-07-14 20:32:42 -06:00
Zack Scholl f6cafd76fd Merge branch 'master' of github.com:schollz/croc 2019-07-14 19:31:53 -07:00
Zack Scholl fe231fa67a remove machineid from deps 2019-07-14 19:31:44 -07:00
Zack Scholl 6091e9348e update deps 2019-07-08 14:21:29 -06:00
Zack Scholl 57564314b0 bump 6.0.11 2019-07-06 10:17:37 -06:00
Zack 6d9105abfb
Docker (#134)
* docker file works

* add docker info
2019-07-04 18:20:25 -07:00
Zack Scholl ba00eda176 bump 6.0.10 2019-06-20 07:10:37 -07:00
Zack Scholl 1d744f1b4a bump version 2019-06-17 13:28:56 -06:00
Zack Scholl 0519850bc3 update deps 2019-06-17 13:28:29 -06:00
Matthew Helmke e5d59fe563 Small fix (#132)
Just fixing a simple typo.
2019-06-17 07:46:52 -07:00
Zack Scholl f35c5b88b6 bump 2019-06-11 10:05:34 -06:00
Zack Scholl 2e2700988b update deps 2019-06-04 09:31:24 -06:00
Zack Scholl 15034cc6d2 bump version 2019-05-27 08:01:37 -07:00
Zack Scholl b1022a3408 update deps 2019-05-27 07:58:23 -07:00
Zack Scholl 1975745d5f remove after test 2019-05-12 13:10:17 -06:00
Zack Scholl 6b288356b9 remove big file after testing 2019-05-12 13:09:10 -06:00
Zack bcb348a776
Update .travis.yml 2019-05-12 10:22:53 -07:00
Zack Scholl 59b6558ce9 bump 2019-05-12 09:31:22 -06:00
Zack 29915596ed
do cleanup 2019-05-12 08:24:06 -07:00
Zack Scholl 8bdc71a06c version bump 2019-05-12 08:55:42 -06:00
meyermarcel cba650193d Add publishing to scoop bucket (#130) 2019-05-12 07:54:03 -07:00
Zack acae0abb24
Thanks @meyermarcel 2019-05-10 11:59:39 -07:00
meyermarcel a23347a823 Replace deprecated 'archive' key with new 'archives' key (#129) 2019-05-10 11:58:53 -07:00
Zack Scholl c45d3c01e5 bump version 2019-05-10 07:16:00 -06:00
Zack 59736eefd8
Update goreleaser.yml 2019-05-10 06:12:55 -07:00
meyermarcel f5e1bab6b5 Add publishing to homebrew repository (#128) 2019-05-10 06:11:14 -07:00
Zack Scholl ae6ce06836 release not draft 2019-05-09 23:05:20 -06:00
Zack Scholl 30f1233f74 fix tests 2019-05-09 23:02:35 -06:00
Zack Scholl f91d52bead update version 2019-05-09 22:59:33 -06:00
Zack Scholl b71e1e78ca update deps 2019-05-09 22:58:28 -06:00
Zack Scholl 0388e07689 remove flushing 2019-05-08 21:33:30 +00:00
Zack Scholl da54ae060a update deps 2019-05-08 21:13:40 +00:00
Zack Scholl 257607a26f use my logger instead of seelog 2019-05-08 21:03:54 +00:00
Zack Scholl 8d3b240563 check room nil before closing 2019-05-06 14:56:17 -07:00
Zack Scholl ba96be5024 update hash 2019-05-03 21:19:39 -06:00
Zack Scholl bd9c7b5ae9 include hash 2019-05-03 21:19:04 -06:00
Zack Scholl cb69e49283 include hash in version 2019-05-03 20:15:29 -07:00
Zack Scholl a6512975ff fix debug statement 2019-05-03 13:55:17 -07:00
Zack 1f3d30c78e
Use relay as backup to find local ports (#127) 2019-05-03 13:51:27 -07:00
Zack Scholl fef1c3ca3b use imohash 2019-05-03 07:35:27 -07:00
Zack Scholl 9f9b93cf47 share chunk ranges instead of chunks Fixes #125 2019-05-03 07:30:35 -07:00
Zack Scholl 7d91f8200c better cleaning of empty rooms 2019-05-02 20:57:55 -07:00
Zack Scholl 1802ebcd00 use imohash 2019-05-02 20:53:02 -07:00
Zack Scholl ee38e7243e more debug 2019-05-02 20:51:13 -07:00
Zack Scholl da09151db2 more debug 2019-05-02 20:48:21 -07:00
Zack Scholl 63f4553e4b more debug 2019-05-02 20:47:41 -07:00
Zack Scholl 8beaf65007 more debug 2019-05-02 20:45:21 -07:00
Zack Scholl 5e8ef27b85 more debug 2019-05-02 20:44:25 -07:00
Zack Scholl 09575a0c88 more debug 2019-05-02 20:43:39 -07:00
Zack Scholl aeb30ef187 use xxhash 2019-05-02 20:36:49 -07:00
Zack Scholl 711690a0f2 use imohash as default as its faster 2019-05-02 20:28:31 -07:00
Zack Scholl ea115908fc fix readme go get 2019-05-02 18:33:52 -07:00
Zack Scholl 3e6a554532 get local IP 2019-05-02 17:14:24 -07:00
Zack Scholl 38e7cae977 document purged error 2019-05-02 17:12:19 -07:00
Zack Scholl 6f5225ac91 purge errors on successful transfer 2019-05-02 17:11:01 -07:00
Zack Scholl 19efe8b77a fix readme 2019-05-02 17:06:11 -07:00
Zack Scholl b7c817a04a update default.txt 2019-05-02 16:45:37 -07:00
Zack Scholl dccaff32cf default stdout 2019-05-02 16:37:43 -07:00
Zack f2e420cd2c
Merge pull request #124 from schollz/v61
version 6.0.0
2019-05-02 16:32:35 -07:00
Zack 02b0cbed06
Merge branch 'master' into v61 2019-05-02 16:32:15 -07:00
Zack Scholl e29179dd9c update readme 2019-05-02 16:06:57 -07:00
Zack Scholl 2da7fa22ad minor 2019-05-02 13:40:14 -07:00
Zack Scholl 2515cfa31e update version 2019-05-02 13:31:48 -07:00
Zack Scholl 78e4ee2b68 update version 2019-05-02 13:28:28 -07:00
Zack Scholl 2f4e5cdec4 update versoin 2019-05-02 13:25:03 -07:00
Zack Scholl 37b29aebce update version 2019-05-02 13:23:23 -07:00
Zack Scholl 9e61f38707 add go generate code for updating version 2019-05-02 13:14:09 -07:00
Zack Scholl 7377f536fc update ui and readme 2019-05-02 12:08:23 -07:00
Zack Scholl 462fad8d8e modify discover parameters 2019-05-02 11:50:01 -07:00
Zack Scholl 9cf4050913 no limit to sender discoveries 2019-05-02 11:47:19 -07:00
Zack Scholl aae63876d6 use local port 2019-05-02 11:45:42 -07:00
Zack Scholl 7af57b3390 slightly larger bar 2019-05-02 11:44:54 -07:00
Zack Scholl 2e5f33c081 print out securing 2019-05-02 11:44:10 -07:00
Zack Scholl 95c2b0f48a Don't throw error if cannot connect to server 2019-05-02 11:41:03 -07:00
Zack Scholl abc5e3f6c0 move install script 2019-05-02 11:31:26 -07:00
Zack Scholl 2b42c5365c don't show ui each time 2019-05-01 17:52:37 -06:00
Zack Scholl 67f69c892d use external ip in ui 2019-05-01 17:49:49 -06:00
Zack Scholl 359dc4549b share public ip as info 2019-05-01 17:44:09 -06:00
Zack Scholl b109b419de save the extenral ip 2019-05-01 17:27:49 -06:00
Zack Scholl 7162e5e45b collect ipaddr from connecting to tcp 2019-05-01 17:10:02 -06:00
Zack Scholl 494b224db0 fix 2019-05-01 13:49:58 -06:00
Zack Scholl 868051bc2a update ports 2019-05-01 13:48:09 -06:00
Zack Scholl 77b11e3c3f simplify readme 2019-05-01 13:20:30 -06:00
Zack Scholl ecfdb2d440 stdout should erase file 2019-05-01 13:09:47 -06:00
Zack Scholl eceddb364e reduce number of default ports 2019-05-01 12:32:00 -06:00
Zack Scholl 4a27806ffe allow local 2019-05-01 12:30:58 -06:00
Zack Scholl b55af54b10 change message 2019-05-01 12:20:02 -06:00
Zack Scholl e1745757ac change message 2019-05-01 12:17:53 -06:00
Zack Scholl be1c1d6206 change message 2019-05-01 12:16:47 -06:00
Zack Scholl 655ffdb4c0 delete room on errors 2019-05-01 12:11:20 -06:00
Zack Scholl 9f6936e1ff small fix 2019-05-01 12:08:24 -06:00
Zack Scholl 48819a9e03 disable local 2019-05-01 11:59:12 -06:00
Zack Scholl 6ac4343213 increase verbosity 2019-05-01 11:45:13 -06:00
Zack Scholl 29dceee8f4 fixes 2019-05-01 11:39:14 -06:00
Zack Scholl 5bffeabbba print connecting message 2019-05-01 11:03:16 -06:00
Zack Scholl f3e2a260d9 update relay address if a peer is found 2019-05-01 10:38:31 -06:00
Zack Scholl 883dff96b8 sender should be able to connect to the port 2019-05-01 10:33:34 -06:00
Zack Scholl 4be02ad249 get ports from tcp server 2019-04-30 17:39:36 -06:00
Zack Scholl 2c2c3f58ac ifix cliwq! 2019-04-30 23:26:32 +00:00
Zack Scholl ec8768bc70 activate travis 2019-04-30 17:20:11 -06:00
Zack Scholl 1275c6b1b5 get tcp port information from banner 2019-04-30 17:19:10 -06:00
Zack Scholl c5bbdb4cb5 allow banner 2019-04-30 17:09:44 -06:00
Zack Scholl 63ec16f7fb add banner 2019-04-30 17:05:19 -06:00
Zack Scholl 23c9a9cff8 longer bar 2019-04-30 16:26:16 -06:00
Zack Scholl 9952da9f6d use random salt 2019-04-30 16:10:07 -06:00
Zack Scholl e72795985b fix tests with nodisable flag 2019-04-30 15:46:27 -06:00
Zack Scholl a1e5a283f9 move file info stuff 2019-04-30 15:39:59 -06:00
Zack Scholl e8f465060f move todo to wiki 2019-04-30 15:32:52 -06:00
Zack Scholl 002cc0050c can switch between local and nonlocal 2019-04-30 13:07:30 -06:00
Zack Scholl a58a0df910 add peer 2019-04-30 12:55:18 -06:00
Zack Scholl 89e4871af2 redo 2019-04-30 12:49:51 -06:00
Zack Scholl f4d24a1f72 update 2019-04-30 12:46:35 -06:00
Zack Scholl 7060eec8d1 need two ways to connect 2019-04-30 11:39:45 -06:00
Zack Scholl a70aa0a4fc make initial connection 2019-04-30 11:35:27 -06:00
Zack Scholl 8f816304f9 make initial connection 2019-04-30 11:35:02 -06:00
Zack Scholl ce45c53b38 make initial connection 2019-04-30 11:32:11 -06:00
Zack Scholl a35779f718 block connection 2019-04-30 11:30:36 -06:00
Zack Scholl d1780e70b7 disable travis 2019-04-30 11:26:37 -06:00
Zack Scholl 3e9283dc01 add todo 2019-04-30 11:25:04 -06:00
Zack Scholl 2583313602 allow discovery 2019-04-30 11:23:53 -06:00
Zack Scholl b9d2be5378 add discovery 2019-04-30 11:19:03 -06:00
Zack Scholl 962ea50aee add back travis 2019-04-30 11:14:21 -06:00
Zack Scholl d56a25cf76 make sure bar finishes 2019-04-30 10:43:52 -06:00
Zack Scholl 346b2d9881 update deps 2019-04-30 10:28:34 -06:00
Zack Scholl c8fdd4726a simplify ui 2019-04-30 09:24:32 -07:00
Zack Scholl 3bf7635f33 improve ui 2019-04-30 08:58:09 -07:00
Zack Scholl 87d295f62b simplify bar add 2019-04-30 07:51:48 -07:00
Zack Scholl be7c2ad1fb check if missing chunks file exists 2019-04-30 07:47:05 -07:00
Zack Scholl 04844cf72c check if missing chunks file exists 2019-04-30 07:44:16 -07:00
Zack Scholl 6da93ae8da allow resume 2019-04-30 07:29:02 -07:00
Zack Scholl 4f20f3ce43 connect in parallel 2019-04-30 07:07:23 -07:00
Zack Scholl e54045ef5a read until 4 bytes 2019-04-30 07:07:07 -07:00
Zack Scholl 3c051f4283 smaller packet 2019-04-30 06:58:57 -07:00
Zack Scholl 000dfc15be fiX comm 2019-04-30 06:57:45 -07:00
Zack Scholl 330e76e09c fix 2019-04-29 21:33:13 -07:00
Zack Scholl 42d35898b5 progressbar is not accurate in total 2019-04-29 21:25:30 -07:00
Zack Scholl c1c8e39499 working 2019-04-29 20:40:42 -07:00
Zack Scholl 859130a988 add croc test 2019-04-29 19:51:54 -07:00
Zack Scholl 7d1f7adddb remove travis for now 2019-04-29 19:51:44 -07:00
Zack Scholl ac113dfe47 initial part works 2019-04-29 19:50:01 -07:00
Zack Scholl 972dce1ec5 don't hardcode address 2019-04-29 19:20:03 -07:00
Zack Scholl 662bce58a3 allow sending 2019-04-29 19:19:48 -07:00
Zack Scholl 9223fc79e9 allow option to skip encryption 2019-04-29 19:19:25 -07:00
Zack Scholl a17f3096a0 no isclosed 2019-04-29 18:55:37 -07:00
Zack Scholl 6b149480d4 add messaging 2019-04-29 18:03:19 -06:00
Zack Scholl a7f12ca179 need to export encryption 2019-04-29 17:58:37 -06:00
Zack Scholl 7d9b199ca3 works 2019-04-29 17:38:49 -06:00
Zack Scholl 06541ee0d3 encapsulate 2019-04-29 17:29:36 -06:00
Zack Scholl bbd7caa148 remove relay 2019-04-29 17:25:20 -06:00
Zack Scholl ca0b898ca3 add tests 2019-04-29 17:24:37 -06:00
Zack Scholl 3685a887b8 add bytecountdecimal 2019-04-29 17:16:38 -06:00
Zack Scholl 005a206460 update go.mod 2019-04-29 17:12:26 -06:00
Zack Scholl c1d66d5301 add go.sum 2019-04-29 17:12:12 -06:00
Zack Scholl cee4c36f8b prune 2019-04-29 17:12:04 -06:00
Zack Scholl 1661bbb221 remove wina nd zipper 2019-04-29 17:10:06 -06:00
Zack Scholl 7a8801f8f1 add the v5 main 2019-04-29 17:09:37 -06:00
Zack Scholl b52001e064 prune 2019-04-29 17:05:48 -06:00
Zack Scholl 1045bd17b5 update croc 2019-04-29 16:54:31 -06:00
Zack Scholl 1f49966bb1 use new version of croc 2019-04-29 16:48:17 -06:00
Zack Scholl dcc7689816 consolidate utils 2019-04-29 16:35:07 -06:00
Zack Scholl 376591384a add more to tests 2019-04-29 16:33:15 -06:00
Zack Scholl 9030aae880 fix test 2019-04-29 16:24:22 -06:00
Zack Scholl 2414593c91 test sending 40mb 2019-04-29 16:04:47 -06:00
Zack Scholl 5b0c52a97b don't dangle 2019-04-29 15:46:40 -06:00
Zack Scholl ef25c556a9 use pointers 2019-04-29 14:06:18 -06:00
Zack Scholl b9a5f450c5 simplify 2019-04-29 13:53:12 -06:00
Zack Scholl 8dc8783bd4 propogate errors 2019-04-27 17:03:05 -07:00
Zack Scholl f238c4b22c modify api of salt 2019-04-27 16:49:00 -07:00
Zack Scholl 249c0d8ab0 faster encryption by generating key once 2019-04-27 11:15:38 -07:00
Zack Scholl 14dd892377 tcp communication better/simpler 2019-04-27 09:20:03 -07:00
Zack 951b2a2548
Update README.md 2019-04-08 10:41:24 -07:00
Zack Scholl 7c731a90dc update travis go 2019-03-12 12:35:43 -06:00
Zack Scholl 003a2344e4 update deps 2019-03-12 12:32:46 -06:00
Zack 566694f381
bump version 2019-02-18 20:30:47 -08:00
Zack Scholl 9643fe748b update deps 2019-02-16 10:44:19 -08:00
Zack caaaff4bd5
Merge pull request #120 from wxitcode/patch-1
Update README.md
2019-02-01 22:25:10 -08:00
wxitcode e272af8794
Update README.md
Fix display issues
2019-02-02 12:14:27 +08:00
Zack bcce2c021d
update with correct relay information #117 2019-01-05 18:35:33 -08:00
Zack 148b10d666
Update default.txt 2019-01-01 16:10:39 -08:00
Zack Scholl af6cc64786 update deps 2019-01-01 17:01:17 -07:00
Zack Scholl fd8a1ebe7b activate go111modules in travis ci 2018-12-14 08:15:47 -07:00
Zack Scholl 6fa1b4c080 update gomod 2018-12-14 06:44:20 -08:00
Zack Scholl 7839d7f6e2 exclude gui from testing 2018-12-14 06:39:51 -08:00
Zack Scholl 43dbf98705 rotate multicast based on current time 2018-12-14 06:32:44 -08:00
Zack Scholl e58fc14218 customize multicast address 2018-12-14 06:27:55 -08:00
Zack d3fdb4257d
Merge pull request #115 from gonutz/master
Add pure Go Windows GUI
2018-11-20 21:06:17 -08:00
Lars d42a4f82a1 Add pure Go Windows GUI 2018-11-21 00:08:30 +01:00
Zack Scholl eaa3624977 bump version 2018-11-05 20:02:31 -07:00
Zack Scholl 068fdb77fc pass errors all the way back 2018-11-02 06:15:37 -07:00
Zack Scholl 8a882cc174 throttle the progress bar 2018-11-01 19:06:50 -07:00
Zack Scholl be70c8a83d bump version 4.1.3 2018-11-01 09:57:18 -07:00
Zack Scholl cf2363fd4e add missing escape at end of cli app 2018-11-01 09:08:18 -07:00
Zack Scholl 92648e0112 bump version 2018-11-01 08:45:59 -06:00
Zack Scholl 5ad34e1034 update deps 2018-11-01 08:45:22 -06:00
Zack 09f89a4958
Update go.mod 2018-11-01 07:29:23 -07:00
Zack 73aeaec822
Update go.mod 2018-11-01 07:29:11 -07:00
Zack Scholl e0081ea8a8 tell user codephrase is wrong if PAKE fails 2018-11-01 07:26:18 -07:00
Zack Scholl a56334fc60 prompt user if accidently receiving 2018-11-01 07:08:57 -07:00
Zack Scholl aefb15105a recipient quits if trying to connect without sender
Addresses #109
2018-11-01 06:56:40 -07:00
Zack Scholl 2b8f581ca4 check checksum for macos #111 2018-10-30 14:41:52 -07:00
Zack 737049694b
Fixes #110 2018-10-29 05:43:17 -07:00
Zack Scholl 818e590d92 need to do chdir in goroutine 2018-10-24 07:19:03 -07:00
Zack Scholl 034074d7a3 version 4.1.1 2018-10-24 07:52:13 -06:00
Zack Scholl e57f3e3861 need to watch slashes 2018-10-24 06:48:05 -07:00
Zack Scholl 0ca74b010e minor zip fixes
Allows multiple zips.

Need to close file after zipping it.
2018-10-24 06:42:27 -07:00
Zack Scholl fea07cab6c Merge branch 'master' of github.com:schollz/croc 2018-10-23 06:19:56 -07:00
Zack Scholl 562925b5e5 add missing execute bit for config dir 2018-10-23 06:19:53 -07:00
Zack c33ac025a0
Update README.md 2018-10-23 05:59:11 -07:00
Zack 3a53b572f4
Update README.md 2018-10-23 05:58:37 -07:00
Zack 8ae342e128
thanks 2018-10-23 05:55:45 -07:00
Zack Scholl 44f482937d update relay 2018-10-23 05:37:46 -07:00
Zack 8d43a1f63a
Merge pull request #105 from schollz/4.1-sync
4.1 sync
2018-10-23 05:30:59 -07:00
Zack fc38472015
Merge pull request #103 from nicolashardy/patch-1
Improve compression speed
2018-10-23 05:30:28 -07:00
Zack Scholl 61d14be70d add compress test 2018-10-23 05:28:30 -07:00
nicolashardy 20497437fe
Improve compression speed
Use Huffman compression in order to fasten the compression speed as described in https://golang.org/pkg/compress/flate/#NewWriter
2018-10-23 11:05:54 +02:00
Zack Scholl 44af4a8ae3 Merge branch '4.1-sync' of github.com:schollz/croc into 4.1-sync 2018-10-22 20:50:57 -07:00
Zack Scholl 824c49254f update readme 2018-10-22 20:50:36 -07:00
Zack 721567fc72
Create issue_template.md 2018-10-22 20:46:20 -07:00
Zack Scholl 08c84e9f85 connect to tcp in parallel 2018-10-22 20:34:04 -07:00
Zack Scholl edc206e73e fix travis 2018-10-22 20:01:40 -07:00
Zack Scholl c2dd9091ff recipient listens to sender 2018-10-22 19:48:45 -07:00
Zack Scholl e5fcc0d3ee add models 2018-10-22 19:42:39 -07:00
Zack Scholl ea9aa3f8ec recipient websockets should check for errors 2018-10-22 19:41:50 -07:00
Zack Scholl 6a07e1538d sender listens for recipient to close 2018-10-22 19:39:16 -07:00
Zack Scholl ab5df93d10 move reading to goroutine 2018-10-22 19:11:43 -07:00
Zack Scholl db42e96b7e add go111module on 2018-10-22 16:56:19 -07:00
Zack Scholl 3d9bc7193d use latest go 2018-10-22 16:54:57 -07:00
Zack Scholl 3064ceef81 add output folder 2018-10-22 06:36:36 -07:00
Zack Scholl 47931d6ba2 update readme 2018-10-21 11:34:31 -07:00
Zack Scholl 3dc6d44c41 throw error if versions are incompatible 2018-10-21 10:46:04 -07:00
Zack Scholl 380ecc7ff9 update gomod 2018-10-21 10:33:15 -07:00
Zack Scholl 708e6fab8b fix imports 2018-10-21 10:06:14 -06:00
Zack Scholl 45b7eebbb9 use normal import 2018-10-21 09:05:27 -07:00
Zack Scholl 69b19c7e78 recipient also uses codephrase 2018-10-21 08:25:53 -07:00
Zack Scholl dd03cdc6e3 update readme about config file 2018-10-21 08:23:56 -07:00
Zack Scholl 81bc06eabb add configuration file 2018-10-21 08:21:58 -07:00
Zack Scholl 1ae117166a add config default 2018-10-21 07:54:59 -07:00
Zack Scholl 0d17219c87 add initial struct fixes #98 2018-10-21 07:45:05 -07:00
Zack Scholl 9e7661c1b0 update deps 2018-10-21 07:43:45 -07:00
Zack Scholl ace9b35e34 remove utils dependency 2018-10-21 07:38:11 -07:00
Zack Scholl 7371f6f238 remove utils dependency 2018-10-21 07:38:04 -07:00
Zack Scholl 23d451540c update cli 2018-10-21 07:33:29 -07:00
Zack Scholl e591c6afb6 better error message when interrupting 2018-10-21 07:31:35 -07:00
Zack Scholl 9349496111 recipient sends back initial data 2018-10-21 07:25:43 -07:00
Zack Scholl 6e10ed25af recipient sends errors through websockets 2018-10-21 07:23:48 -07:00
Zack Scholl d05e196139 return errors through websockets 2018-10-21 07:20:23 -07:00
Zack Scholl 304355af48 update pake 2018-10-21 07:10:36 -07:00
Zack 50a64d04da
Update README.md 2018-10-20 07:14:36 -07:00
Zack Scholl 4aab058344 add windows icon 2018-10-20 07:02:51 -07:00
Zack Scholl 06e8260e50 bump version 2018-10-19 10:35:54 -07:00
Zack Scholl dc6493374a open folder if no arguments given 2018-10-19 10:18:49 -07:00
Zack Scholl 5ecbab6673 fix release 2018-10-19 07:54:20 -07:00
Zack Scholl f94790dc75 add release 2018-10-19 07:50:43 -07:00
Zack Scholl 92af0b46ab add release 2018-10-19 07:46:42 -07:00
Zack Scholl 4e55b1efd1 don't do debug 2018-10-19 07:33:08 -07:00
Zack Scholl 0e4fff7378 open folder after receiving 2018-10-19 07:30:24 -07:00
Zack Scholl 79f7e9af41 add icons 2018-10-19 07:25:22 -07:00
Zack Scholl 62bf674365 add more info to win 2018-10-19 06:36:45 -07:00
Zack Scholl 2fc216cb1b bump 2018-10-18 09:35:51 -07:00
Zack Scholl ec148d98c1 make sure recipient connects to TCP first 2018-10-18 09:35:08 -07:00
Zack Scholl 365eca9653 update goreleaser 2018-10-18 07:54:25 -06:00
Zack Scholl 987a21fb8f bump version 2018-10-18 07:53:06 -06:00
Zack Scholl e85eaac9e3 add parent window 2018-10-18 06:45:32 -07:00
Zack Scholl 366d3c527c fix fprintf 2018-10-18 06:40:24 -07:00
Zack Scholl 3b498d57cf switch to window 2018-10-18 06:36:16 -07:00
Zack Scholl 82e274875d fix zipping on windows 2018-10-18 06:34:48 -07:00
Zack Scholl e47393031b bump version 2018-10-17 23:14:46 -06:00
Zack Scholl 4d35b3a397 reduce goreleaser 2018-10-17 23:11:02 -06:00
Zack Scholl 48933b5ecc better ui for window 2018-10-17 21:38:29 -07:00
Zack Scholl f9dfa6bc05 add window recipient prompt 2018-10-17 18:14:45 -07:00
Zack Scholl 4ee008225e add makefile for the windows version 2018-10-17 16:57:36 -07:00
Zack Scholl 24e0573116 update progressbar 2018-10-17 10:20:09 -07:00
Zack 62e7629466
Merge pull request #94 from schollz/wincroc
Wincroc
2018-10-17 07:55:56 -07:00
Zack Scholl 56e0068129 send file works 2018-10-17 07:41:13 -07:00
Zack Scholl 93942f4e0c give stop signals to servers 2018-10-17 07:38:21 -07:00
Zack Scholl 157ab169aa sending is working for wincroc 2018-10-17 07:01:44 -07:00
Zack Scholl 6a899492f5 add state 2018-10-17 06:39:02 -07:00
Zack Scholl 47ab799c6f add file stats to state 2018-10-17 06:19:01 -07:00
Zack Scholl 55d9137b6d add state 2018-10-17 06:13:38 -07:00
Zack Scholl 3bed0bc8bf move files here 2018-10-17 06:13:38 -07:00
Zack Scholl 8734394bb8 merge sender and recipient into croc 2018-10-17 06:13:38 -07:00
Zack Scholl 0bbf2841ca use build tags 2018-10-16 15:59:04 -07:00
Zack Scholl 144102a721 window based croc 2018-10-16 15:48:22 -07:00
Zack Scholl 9a41d9099b move main to cli 2018-10-16 12:23:01 -07:00
Zack Scholl 49a73d7183 update readme 2018-10-14 16:27:07 -07:00
Zack 76da134a2f
Update README.md 2018-10-14 07:15:47 -07:00
Zack f7487e8589
Update README.md 2018-10-13 11:25:35 -07:00
Zack ad697febf4
Update default.txt 2018-10-13 11:03:15 -07:00
Zack 8662961e93
Update README.md 2018-10-13 10:50:29 -07:00
Zack 28083f3204
Rename install.sh to default.txt 2018-10-13 10:46:39 -07:00
Zack da94e54d7d
Update install.sh 2018-10-13 10:36:32 -07:00
Zack 267134dc6c
Create install.sh 2018-10-13 10:23:16 -07:00
72 changed files with 8128 additions and 2677 deletions

BIN
.github/1.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

BIN
.github/2.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

BIN
.github/3.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

BIN
.github/4.gif vendored

Binary file not shown.

Before

Width:  |  Height:  |  Size: 351 KiB

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
github: schollz

9
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,9 @@
---
name: New issue
about: Create an issue
title: ''
assignees: ''
---
*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.

10
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"

52
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,52 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
unit-tests:
name: Go unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
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

64
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,64 @@
# This is a basic workflow to help you get started with Actions
name: CD
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches:
- '*'
tags:
- 'v*'
pull_request:
branches:
- '*'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Docker meta
id: docker_meta
uses: docker/metadata-action@v5
with:
images: schollz/croc
# generate Docker tags based on the following events/attributes
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm,linux/arm64,linux/386
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}

131
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,131 @@
name: Make release
on:
release:
types: [created]
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v4
with:
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 }}
cd croc-${{ github.event.release.name }} && go mod tidy && go mod vendor
cd .. && tar -czvf croc_${{ github.event.release.name }}_src.tar.gz croc-${{ github.event.release.name }}
- name: Build files
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows-64bit.zip croc.exe LICENSE
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows-32bit.zip croc.exe LICENSE
CGO_ENABLED=0 GOOS=windows GOARCH=arm go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows-ARM.zip croc.exe LICENSE
CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows-ARM64.zip croc.exe LICENSE
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc
tar -czvf croc_${{ github.event.release.name }}_Linux-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc
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
tar -czvf croc_${{ github.event.release.name }}_macOS-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -ldflags '-s -extldflags "-sectcreate __TEXT __info_plist Info.plist"' -o croc
tar -czvf croc_${{ github.event.release.name }}_macOS-ARM64.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=dragonfly GOARCH=amd64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_DragonFlyBSD-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=freebsd GOARCH=amd64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_FreeBSD-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=freebsd GOARCH=arm64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_FreeBSD-ARM64.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=netbsd GOARCH=386 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_NetBSD-32bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=netbsd GOARCH=amd64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_NetBSD-64bit.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=netbsd GOARCH=arm64 go build -ldflags '' -o croc
tar -czvf croc_${{ github.event.release.name }}_NetBSD-ARM64.tar.gz croc LICENSE
CGO_ENABLED=0 GOOS=openbsd GOARCH=amd64 go build -ldflags '' -o croc
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
sha256sum croc_${{ github.event.release.name }}_src.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows-64bit.zip >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows-32bit.zip >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows-ARM.zip >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows-ARM64.zip >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows7-64bit.zip >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_Windows7-32bit.zip >> croc_${{ github.event.release.name }}_checksums.txt
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
sha256sum croc_${{ github.event.release.name }}_DragonFlyBSD-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_FreeBSD-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_FreeBSD-ARM64.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_NetBSD-32bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_NetBSD-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_NetBSD-ARM64.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_OpenBSD-64bit.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
sha256sum croc_${{ github.event.release.name }}_OpenBSD-ARM64.tar.gz >> croc_${{ github.event.release.name }}_checksums.txt
- name: Release
uses: softprops/action-gh-release@v2
with:
files: |
croc_${{ github.event.release.name }}_checksums.txt
croc_${{ github.event.release.name }}_src.tar.gz
croc_${{ github.event.release.name }}_Windows-64bit.zip
croc_${{ github.event.release.name }}_Windows-32bit.zip
croc_${{ github.event.release.name }}_Windows-ARM.zip
croc_${{ github.event.release.name }}_Windows-ARM64.zip
croc_${{ github.event.release.name }}_Windows7-64bit.zip
croc_${{ github.event.release.name }}_Windows7-32bit.zip
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
croc_${{ github.event.release.name }}_DragonFlyBSD-64bit.tar.gz
croc_${{ github.event.release.name }}_FreeBSD-64bit.tar.gz
croc_${{ github.event.release.name }}_FreeBSD-ARM64.tar.gz
croc_${{ github.event.release.name }}_NetBSD-32bit.tar.gz
croc_${{ github.event.release.name }}_NetBSD-64bit.tar.gz
croc_${{ github.event.release.name }}_NetBSD-ARM64.tar.gz
croc_${{ github.event.release.name }}_OpenBSD-64bit.tar.gz
croc_${{ github.event.release.name }}_OpenBSD-ARM64.tar.gz

27
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,27 @@
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
#
# You can adjust the behavior by modifying this file.
# For more information, see:
# https://github.com/actions/stale
name: Mark stale issues and pull requests
on:
schedule:
- cron: '19 12 * * *'
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Stale issue message'
stale-pr-message: 'Stale pull request message'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'

14
.github/workflows/winget.yml vendored Normal file
View File

@ -0,0 +1,14 @@
name: Publish to Winget
on:
release:
types: [released]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: vedantmgoyal2009/winget-releaser@v2
with:
identifier: schollz.croc
installers-regex: '_Windows-\w+\.zip$'
token: ${{ secrets.WINGET_TOKEN }}

13
.gitignore vendored Normal file
View File

@ -0,0 +1,13 @@
# Binaries
/croc
/croc.exe
zsh_autocomplete
bash_autocomplete
dist
bin
croc-stdin*
.idea/
.vscode/
src/utils/bigfile.test
test1/

100
.goreleaser.yml Normal file
View File

@ -0,0 +1,100 @@
project_name: croc
build:
main: main.go
binary: croc
ldflags: -s -w -X main.Version="v{{.Version}}-{{.Date}}"
env:
- CGO_ENABLED=0
goos:
- darwin
- linux
- windows
- freebsd
- netbsd
- openbsd
- dragonfly
goarch:
- amd64
- 386
- arm
- arm64
ignore:
- goos: darwin
goarch: 386
- goos: freebsd
goarch: arm
goarm:
- 7
nfpms:
-
formats:
- deb
vendor: "schollz.com"
homepage: "https://schollz.com/software/croc/"
maintainer: "Zack Scholl <zack.scholl@gmail.com>"
description: "A simple, secure, and fast way to transfer data."
license: "MIT"
file_name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
replacements:
amd64: 64bit
386: 32bit
arm: ARM
arm64: ARM64
darwin: macOS
linux: Linux
windows: Windows
openbsd: OpenBSD
netbsd: NetBSD
freebsd: FreeBSD
dragonfly: DragonFlyBSD
archives:
-
format: tar.gz
format_overrides:
- goos: windows
format: zip
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
replacements:
amd64: 64bit
386: 32bit
arm: ARM
arm64: ARM64
darwin: macOS
linux: Linux
windows: Windows
openbsd: OpenBSD
netbsd: NetBSD
freebsd: FreeBSD
dragonfly: DragonFlyBSD
files:
- README.md
- LICENSE
- zsh_autocomplete
- bash_autocomplete
brews:
-
tap:
owner: schollz
name: homebrew-tap
folder: Formula
description: "croc is a tool that allows any two computers to simply and securely transfer files and folders."
homepage: "https://schollz.com/software/croc/"
install: |
bin.install "croc"
test: |
system "#{bin}/croc --version"
scoop:
bucket:
owner: schollz
name: scoop-bucket
homepage: "https://schollz.com/software/croc/"
description: "croc is a tool that allows any two computers to simply and securely transfer files and folders."
license: MIT
announce:
twitter:
# Wether its enabled or not.
# Defaults to false.
enabled: false

View File

@ -6,6 +6,18 @@ go:
env:
- "PATH=/home/travis/gopath/bin:$PATH"
install: true
script:
- go build -v
- go test -v -cover ./...
- env GO111MODULE=on go build -v
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/compress
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/croc
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/crypt
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/tcp
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/utils
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v10/src/comm
branches:
except:
- dev
- win

16
Dockerfile Normal file
View File

@ -0,0 +1,16 @@
FROM golang:1.22-alpine as builder
RUN apk add --no-cache git gcc musl-dev
WORKDIR /go/croc
COPY . .
RUN go build -v -ldflags="-s -w"
FROM alpine:latest
EXPOSE 9009
EXPOSE 9010
EXPOSE 9011
EXPOSE 9012
EXPOSE 9013
COPY --from=builder /go/croc/croc /go/croc/croc-entrypoint.sh /
USER nobody
ENTRYPOINT ["/croc-entrypoint.sh"]
CMD ["relay"]

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017 Zack
Copyright (c) 2017-2024 Zack
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

410
README.md
View File

@ -1,129 +1,281 @@
<p align="center">
<img
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-4.0.3-brightgreen.svg?style=flat-square" alt="Version"></a>
<img src="https://img.shields.io/badge/coverage-77%25-brightgreen.svg?style=flat-square" alt="Code coverage">
<a href="https://travis-ci.org/schollz/croc"><img
src="https://img.shields.io/travis-ci/schollz/croc.svg?style=flat-square" alt="Build
Status"></a>
<a href="https://saythanks.io/to/schollz"><img src="https://img.shields.io/badge/Say%20Thanks-!-brightgreen.svg?style=flat-square" alt="Say thanks"></a>
</p>
<p align="center">Easily and securely transfer stuff from one computer to another.</p>
*croc* is a tool that allows any two computers to simply and securely transfer files and folders. There are many tools that can do this, but afaik *croc* is the only tool that is easily installed on any platform *and* has secure peer-to-peer transferring *and* has the capability to resume broken transfers.
## Overview
*croc* uses "code phrases" to securely transfer files. A code phrase is a combination of three random words (mnemonicoded 4 bytes) which the sender shares with the recipient. The code phrase is used by the sender and recipient for password authenticated key exchange ([PAKE](https://github.com/schollz/pake)) to validate parties and generate a secure session key for end-to-end encryption. Since a code phrase can only be used once between two parties, an attacker has a chance of less than 1 in *4 billion* to guess the right code phrase to steal the file. Any attacker with the wrong code phrase will fail the PAKE and the sender will be notified. Only two people with the right code phrase will be able to computers transfer encrypted data through a relay.
The actual data transfer is accomplished using a relay, either using raw TCP sockets or websockets. If both computers are on the LAN network then *croc* will use a local relay, otherwise a public relay is used. All the data going through the relay is encrypted using the PAKE-generated session key, so the relay can't spy on information passing through it. The data is transferred in blocks, where each block is compressed and encrypted, and the recipient keeps track of blocks received so that it can resume the transfer if interrupted.
My motivation to write *croc*, as stupid as it sounds, is because I wanted to create a program that made it easy to send a 3GB+ PBS documentary to my friend in a different country. My friend has a Windows computer and is not comfortable using a terminal. So I wanted to write a program that, while secure, is simple to receive a file. *croc* accomplishes this, and now I find myself using it almost everyday at work. To receive a file you can just download the executable and double click on it (sending a file requires opening a terminal still, though).
## Examples
The first example shows the basic transfer of some file or folder from computer 1 to computer 2. _These two gifs should run in sync if you force-reload (Ctl+F5)_
![send](.github/1.gif)
![receive](.github/2.gif)
The second example shows how you can restart a broken transfer. Here, computer 2 presses Ctl+C during a transfer to abruptly break the connection, and then resumes by having computer 1 re-send the file. _These two gifs should run in sync if you force-reload (Ctl+F5)_
![send](.github/3.gif)
![receive](.github/4.gif)
## Install
[Download the latest release for your system](https://github.com/schollz/croc/releases/latest).
Or, you can [install Go](https://golang.org/dl/) and build from source with `go get github.com/schollz/croc`.
## Usage
The basic usage is to just do
```
$ croc send FILE
```
to send and then on the other computer you can just do
```
$ croc [code phrase]
```
to receive (you'll be prompted to enter the code phrase). Note, by default, you don't need any arguments for receiving, instead you will be prompted to enter the code phrase. This makes it possible for you to just double click the executable to run (nice for those of us that aren't computer wizards).
### Custom code phrase
You can send with your own code phrase (must be more than 4 characters).
```
$ croc send --code [code phrase] [filename]
```
### Use locally
*croc* automatically will attempt to start a local connection on your LAN to transfer the file much faster. It uses [peer discovery](https://github.com/schollz/peerdiscovery), basically broadcasting a message on the local subnet to see if another *croc* user wants to receive the file. *croc* will utilize the first incoming connection from either the local network or the public relay and follow through with PAKE.
You can change this behavior by forcing *croc* to use only local connections (`--local`) or force to use the public relay only (`--no-local`):
```
$ croc --local/--no-local send [filename]
```
### Using pipes - stdin and stdout
You can easily use *croc* in pipes when you need to send data through stdin or get data from stdout. To send you can just use pipes:
```
$ cat [filename] | croc send
```
In this case *croc* will automatically use the stdin data and send and assign a filename like "croc-stdin-123456789". To receive to stdout at you can always just use the `-yes` and `-stdout` flags which will automatically approve the transfer and pipe it out to stdout.
```
$ croc -yes -stdout [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.
### Self-host relay
The relay is needed to staple the parallel incoming and outgoing connections. The relay temporarily stores connection information and the encrypted meta information. The default uses a public relay at, `ws://198.199.67.130:8153`. You can also run your own relay, it is very easy, just run:
```
$ croc relay
```
Make sure to open up TCP ports (see `croc relay --help` for which ports to open). Relays can also be customized to which elliptic curve they will use (default is siec).
You can send files using your relay by entering `-relay` to change the relay that you are using if you want to custom host your own.
```
$ croc -relay "ws://myrelay.example.com" send [filename]
```
## License
MIT
## Acknowledgements
*croc* has been through many iterations, and I am awed by all the great contributions! If you feel like contributing, in any way, by all means you can send an Issue, a PR, ask a question, or tweet me ([@yakczar](http://ctt.ec/Rq054)).
Thanks...
- ...[@warner](https://github.com/warner) for the [idea](https://github.com/warner/magic-wormhole).
- ...[@tscholl2](https://github.com/tscholl2) for the [encryption gists](https://gist.github.com/tscholl2/dc7dc15dc132ea70a98e8542fefffa28).
- ...[@skorokithakis](https://github.com/skorokithakis) for [code on proxying two connections](https://www.stavros.io/posts/proxying-two-connections-go/).
- ...for making pull requests [@Girbons](https://github.com/Girbons), [@techtide](https://github.com/techtide), [@heymatthew](https://github.com/heymatthew), [@Lunsford94](https://github.com/Lunsford94), [@lummie](https://github.com/lummie), [@jesuiscamille](https://github.com/jesuiscamille), [@threefjord](https://github.com/threefjord), [@marcossegovia](https://github.com/marcossegovia), [@csleong98](https://github.com/csleong98), [@afotescu](https://github.com/afotescu), [@callmefever](https://github.com/callmefever), [@El-JojA](https://github.com/El-JojA), [@anatolyyyyyy](https://github.com/anatolyyyyyy), [@goggle](https://github.com/goggle), [@smileboywtu](https://github.com/smileboywtu)!
<p align="center">
<img
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.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>
<p align="center">This project is supported by <a href="https://github.com/sponsors/schollz">Github sponsors</a>.</p>
`croc` is a tool that allows any two computers to simply and securely transfer files and folders. AFAIK, *croc* is the only CLI file-transfer tool that does **all** of the following:
- allows **any two computers** to transfer data (using a relay)
- provides **end-to-end encryption** (using PAKE)
- enables easy **cross-platform** transfers (Windows, Linux, Mac)
- allows **multiple file** transfers
- allows **resuming transfers** that are interrupted
- local server or port-forwarding **not needed**
- **ipv6-first** with ipv4 fallback
- can **use proxy**, like tor
For more information about `croc`, see [my blog post](https://schollz.com/software/croc6) or read a [recent interview I did](https://console.substack.com/p/console-91).
![Example](src/install/customization.gif)
## Install
Download [the latest release for your system](https://github.com/schollz/croc/releases/latest), or install a release from the command-line:
```
curl https://getcroc.schollz.com | bash
```
On macOS you can install the latest release with [Homebrew](https://brew.sh/):
```
brew install croc
```
On macOS you can also install the latest release with [MacPorts](https://macports.org/):
```
sudo port selfupdate
sudo port install croc
```
On Windows you can install the latest release with [Scoop](https://scoop.sh/), [Chocolatey](https://chocolatey.org), or [Winget](https://learn.microsoft.com/en-us/windows/package-manager/):
```
scoop install croc
```
```
choco install croc
```
```
winget install schollz.croc
```
On Unix you can install the latest release with [Nix](https://nixos.org/nix):
```
nix-env -i croc
```
On Alpine Linux you have to install dependencies first:
```
apk add bash coreutils
wget -qO- https://getcroc.schollz.com | bash
```
On Arch Linux you can install the latest release with `pacman`:
```
pacman -S croc
```
On Fedora you can install with `dnf`:
```
dnf install croc
```
On Gentoo you can install with `portage`:
```
emerge net-misc/croc
```
On Termux you can install with `pkg`:
```
pkg install croc
```
On FreeBSD you can install with `pkg`:
```
pkg install croc
```
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
```
On Android there is a 3rd party F-Droid app [available to download](https://f-droid.org/en/packages/com.github.howeyc.crocgui/).
## Usage
To send a file, simply do:
```
$ croc send [file(s)-or-folder]
Sending 'file-or-folder' (X MB)
Code is: code-phrase
```
Then to receive the file (or folder) on another computer, you can just do
```
croc code-phrase
```
The code phrase is used to establish password-authenticated key agreement ([PAKE](https://en.wikipedia.org/wiki/Password-authenticated_key_agreement)) which generates a secret key for the sender and recipient to use for end-to-end encryption.
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).
```
croc send --code [code-phrase] [file(s)-or-folder]
```
### Allow overwriting without prompt
By default, croc will prompt whether to overwrite a file. You can automatically overwrite files by using the `--overwrite` flag (recipient only). For example, receive a file to automatically overwrite:
```
croc --yes --overwrite <code>
```
### Use pipes - stdin and stdout
You can pipe to `croc`:
```
cat [filename] | croc send
```
In this case `croc` will automatically use the stdin data and send and assign a filename like "croc-stdin-123456789". To receive to `stdout` at you can always just use the `--yes` will automatically approve the transfer and pipe it out to `stdout`.
```
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
Sometimes you want to send URLs or short text. In addition to piping, you can easily send text with `croc`:
```
croc send --text "hello world"
```
This will automatically tell the receiver to use `stdout` when they receive the text so it will be displayed.
### Use a proxy
You can use a proxy as your connection to the relay by adding a proxy address with `--socks5`. For example, you can send via a tor relay:
```
croc --socks5 "127.0.0.1:9050" send SOMEFILE
```
### Change encryption curve
You can choose from several different elliptic curves to use for encryption by using the `--curve` flag. Only the recipient can choose the curve. For example, receive a file using the P-521 curve:
```
croc --curve p521 <codephrase>
```
Available curves are P-256, P-348, P-521 and SIEC. P-256 is the default curve.
### Change hash algorithm
You can choose from several different hash algorithms. The default is the `xxhash` algorithm which is fast and thorough. If you want to optimize for speed you can use the `imohash` algorithm which is even faster, but since it samples files (versus reading the whole file) it can mistakenly determine that a file is the same on the two computers transferring - though this is only a problem if you are syncing files versus sending a new file to a computer.
```
croc send --hash imohash SOMEFILE
```
### Self-host relay
The relay is needed to staple the parallel incoming and outgoing connections. By default, `croc` uses a public relay but you can also run your own relay:
```
croc relay
```
By default it uses TCP ports 9009-9013. Make sure to open those up. You can customize the ports (e.g. `croc relay --ports 1111,1112`), but you must have a minimum of **2** ports for the relay. The first port is for communication and the subsequent ports are used for the multiplexed data transfer.
You can send files using your relay by entering `--relay` to change the relay that you are using if you want to custom host your own.
```
croc --relay "myrelay.example.com:9009" send [filename]
```
Note, when sending, you only need to include the first port (the communication port). The subsequent ports for data transfer will be transmitted back to the user from the relay.
#### Self-host relay (docker)
If it's easier you can also run a relay with Docker:
```
docker run -d -p 9009-9013:9009-9013 -e CROC_PASS='YOURPASSWORD' schollz/croc
```
Be sure to include the password for the relay otherwise any requests will be rejected.
```
croc --pass YOURPASSWORD --relay "myreal.example.com:9009" send [filename]
```
Note: when including `--pass YOURPASSWORD` you can instead pass a file with the password, e.g. `--pass FILEWITHPASSWORD`.
## License
MIT
## Acknowledgements
`croc` has gone through many iterations, and I am awed by all the great contributions! If you feel like contributing, in any way, by all means you can send an Issue, a PR, or ask a question.
Thanks [@warner](https://github.com/warner) for the [idea](https://github.com/warner/magic-wormhole), [@tscholl2](https://github.com/tscholl2) for the [encryption gists](https://gist.github.com/tscholl2/dc7dc15dc132ea70a98e8542fefffa28), [@skorokithakis](https://github.com/skorokithakis) for [code on proxying two connections](https://www.stavros.io/posts/proxying-two-connections-go/). Finally thanks for making pull requests [@maximbaz](https://github.com/maximbaz), [@meyermarcel](https://github.com/meyermarcel), [@Girbons](https://github.com/Girbons), [@techtide](https://github.com/techtide), [@heymatthew](https://github.com/heymatthew), [@Lunsford94](https://github.com/Lunsford94), [@lummie](https://github.com/lummie), [@jesuiscamille](https://github.com/jesuiscamille), [@threefjord](https://github.com/threefjord), [@marcossegovia](https://github.com/marcossegovia), [@csleong98](https://github.com/csleong98), [@afotescu](https://github.com/afotescu), [@callmefever](https://github.com/callmefever), [@El-JojA](https://github.com/El-JojA), [@anatolyyyyyy](https://github.com/anatolyyyyyy), [@goggle](https://github.com/goggle), [@smileboywtu](https://github.com/smileboywtu), [@nicolashardy](https://github.com/nicolashardy), [@fbartels](https://github.com/fbartels), [@rkuprov](https://github.com/rkuprov), [@hreese](https://github.com/hreese), [@xenrox](https://github.com/xenrox) and [Ipar](https://github.com/lpar)!

6
croc-entrypoint.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
set -e
if [ -n "$CROC_PASS" ]; then
set -- --pass "$CROC_PASS" "$@"
fi
exec /croc "$@"

12
croc.service Normal file
View File

@ -0,0 +1,12 @@
[Unit]
Description=croc relay
After=network.target
[Service]
Type=simple
DynamicUser=yes
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
ExecStart=/usr/bin/croc relay
[Install]
WantedBy=multi-user.target

56
go.mod
View File

@ -1,23 +1,39 @@
module github.com/schollz/croc
module github.com/schollz/croc/v10
go 1.22
toolchain go1.23.1
require (
github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575
github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d
github.com/fatih/color v1.7.0 // indirect
github.com/gorilla/websocket v1.4.0
github.com/mars9/crypt v0.0.0-20150406101210-65899cf653ff // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
github.com/mattn/go-isatty v0.0.4 // indirect
github.com/pkg/errors v0.8.0
github.com/schollz/mnemonicode v1.0.1
github.com/schollz/pake v1.0.2
github.com/schollz/peerdiscovery v1.2.2
github.com/schollz/progressbar/v2 v2.5.3
github.com/schollz/spinner v0.0.0-20180925172146-6bbc5f7804f9
github.com/schollz/utils v1.0.0
github.com/stretchr/testify v1.2.2
github.com/tscholl2/siec v0.0.0-20180721101609-21667da05937
github.com/urfave/cli v1.20.0
golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 // indirect
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.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/pake/v3 v3.0.5
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.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/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
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/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

148
go.sum Normal file
View File

@ -0,0 +1,148 @@
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/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=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
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.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/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-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=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI=
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs=
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/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.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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
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=
github.com/tscholl2/siec v0.0.0-20210707234609-9bdfc483d499/go.mod h1:KL9+ubr1JZdaKjgAaHr+tCytEncXBa1pR6FjbTsOJnw=
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 h1:sDWDZkwYqX0jvLWstKzFwh+pYhQNaVg65BgSkCP/f7U=
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406/go.mod h1:KL9+ubr1JZdaKjgAaHr+tCytEncXBa1pR6FjbTsOJnw=
github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.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.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.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/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=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.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/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.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.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/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=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,66 +0,0 @@
project_name: croc
build:
main: main.go
binary: croc
ldflags: -s -w -X main.Version="v{{.Version}}-{{.Date}}"
env:
- CGO_ENABLED=0
goos:
- darwin
- linux
- windows
- freebsd
- netbsd
- openbsd
- dragonfly
goarch:
- amd64
- 386
- arm
- arm64
goarm:
- 7
nfpm:
formats:
- deb
vendor: "schollz.com"
homepage: "https://schollz.com/software/croc/"
maintainer: "Zack Scholl <zack.scholl@gmail.com>"
description: "A simple, secure, and fast way to transfer data."
license: "MIT"
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
replacements:
amd64: 64bit
386: 32bit
arm: ARM
arm64: ARM64
darwin: macOS
linux: Linux
windows: Windows
openbsd: OpenBSD
netbsd: NetBSD
freebsd: FreeBSD
dragonfly: DragonFlyBSD
archive:
format: tar.gz
format_overrides:
- goos: windows
format: zip
name_template: "{{.ProjectName}}_{{.Version}}_{{.Os}}-{{.Arch}}"
replacements:
amd64: 64bit
386: 32bit
arm: ARM
arm64: ARM64
darwin: macOS
linux: Linux
windows: Windows
openbsd: OpenBSD
netbsd: NetBSD
freebsd: FreeBSD
dragonfly: DragonFlyBSD
files:
- README.md
- LICENSE
release:
draft: true

247
main.go
View File

@ -1,210 +1,55 @@
package main
import (
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
//go:generate go run src/install/updateversion.go
//go:generate git commit -am "bump $VERSION"
//go:generate git tag -af v$VERSION -m "v$VERSION"
humanize "github.com/dustin/go-humanize"
"github.com/schollz/croc/src/croc"
"github.com/schollz/croc/src/utils"
"github.com/urfave/cli"
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/schollz/croc/v10/src/cli"
"github.com/schollz/croc/v10/src/utils"
)
var Version string
var codePhrase string
var cr *croc.Croc
func main() {
app := cli.NewApp()
app.Name = "croc"
if Version == "" {
Version = "dev"
}
// "github.com/pkg/profile"
// go func() {
// for {
// f, err := os.Create("croc.pprof")
// if err != nil {
// panic(err)
// }
// runtime.GC() // get up-to-date statistics
// if err := pprof.WriteHeapProfile(f); err != nil {
// panic(err)
// }
// f.Close()
// time.Sleep(3 * time.Second)
// fmt.Println("wrote profile")
// }
// }()
app.Version = Version
app.Compiled = time.Now()
app.Usage = "easily and securely transfer stuff from one computer to another"
app.UsageText = "croc allows any two computers to directly and securely transfer files"
// app.ArgsUsage = "[args and such]"
app.Commands = []cli.Command{
{
Name: "send",
Usage: "send a file",
Description: "send a file over the relay",
ArgsUsage: "[filename]",
Flags: []cli.Flag{
cli.BoolFlag{Name: "no-compress, o", Usage: "disable compression"},
cli.BoolFlag{Name: "no-encrypt, e", Usage: "disable encryption"},
cli.StringFlag{Name: "code, c", Usage: "codephrase used to connect to relay"},
},
HelpName: "croc send",
Action: func(c *cli.Context) error {
return send(c)
},
},
{
Name: "relay",
Usage: "start a croc relay",
Description: "the croc relay will handle websocket and TCP connections",
Flags: []cli.Flag{},
HelpName: "croc relay",
Action: func(c *cli.Context) error {
return relay(c)
},
},
}
app.Flags = []cli.Flag{
cli.StringFlag{Name: "addr", Value: "198.199.67.130", Usage: "address of the public relay"},
cli.StringFlag{Name: "addr-ws", Value: "8153", Usage: "port of the public relay websocket server to connect"},
cli.StringFlag{Name: "addr-tcp", Value: "8154,8155,8156,8157,8158,8159,8160,8161", Usage: "tcp ports of the public relay server to connect"},
cli.BoolFlag{Name: "no-local", Usage: "disable local mode"},
cli.BoolFlag{Name: "local", Usage: "use only local mode"},
cli.BoolFlag{Name: "debug", Usage: "increase verbosity (a lot)"},
cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"},
cli.BoolFlag{Name: "stdout", Usage: "redirect file to stdout"},
cli.BoolFlag{Name: "force-tcp", Usage: "force TCP"},
cli.BoolFlag{Name: "force-web", Usage: "force websockets"},
cli.StringFlag{Name: "port", Value: "8153", Usage: "port that the websocket listens on"},
cli.StringFlag{Name: "tcp-port", Value: "8154,8155,8156,8157,8158,8159,8160,8161", Usage: "ports that the tcp server listens on"},
cli.StringFlag{Name: "curve", Value: "siec", Usage: "specify elliptic curve to use (p224, p256, p384, p521, siec)"},
}
app.EnableBashCompletion = true
app.HideHelp = false
app.HideVersion = false
app.BashComplete = func(c *cli.Context) {
fmt.Fprintf(c.App.Writer, "send\nreceive\relay")
}
app.Action = func(c *cli.Context) error {
return receive(c)
}
app.Before = func(c *cli.Context) error {
cr = croc.Init(c.GlobalBool("debug"))
cr.AllowLocalDiscovery = true
cr.Address = c.GlobalString("addr")
cr.AddressTCPPorts = strings.Split(c.GlobalString("addr-tcp"), ",")
cr.AddressWebsocketPort = c.GlobalString("addr-ws")
cr.NoRecipientPrompt = c.GlobalBool("yes")
cr.Stdout = c.GlobalBool("stdout")
cr.LocalOnly = c.GlobalBool("local")
cr.NoLocal = c.GlobalBool("no-local")
cr.ShowText = true
cr.RelayWebsocketPort = c.String("port")
cr.RelayTCPPorts = strings.Split(c.String("tcp-port"), ",")
cr.CurveType = c.String("curve")
if c.GlobalBool("force-tcp") {
cr.ForceSend = 2
}
if c.GlobalBool("force-web") {
cr.ForceSend = 1
}
return nil
}
// Create a channel to receive OS signals
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
err := app.Run(os.Args)
if err != nil {
fmt.Printf("\nerror: %s", err.Error())
}
}
func send(c *cli.Context) error {
stat, _ := os.Stdin.Stat()
var fname string
if (stat.Mode() & os.ModeCharDevice) == 0 {
f, err := ioutil.TempFile(".", "croc-stdin-")
if err != nil {
return err
}
_, err = io.Copy(f, os.Stdin)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
fname = f.Name()
defer func() {
err = os.Remove(fname)
if err != nil {
log.Println(err)
}
}()
} else {
fname = c.Args().First()
}
if fname == "" {
return errors.New("must specify file: croc send [filename]")
}
cr.UseCompression = !c.Bool("no-compress")
cr.UseEncryption = !c.Bool("no-encrypt")
if c.String("code") != "" {
codePhrase = c.String("code")
}
if len(codePhrase) == 0 {
// generate code phrase
codePhrase = utils.GetRandomName()
}
// print the text
finfo, err := os.Stat(fname)
if err != nil {
return err
}
fname, _ = filepath.Abs(fname)
fname = filepath.Clean(fname)
_, filename := filepath.Split(fname)
fileOrFolder := "file"
fsize := finfo.Size()
if finfo.IsDir() {
fileOrFolder = "folder"
fsize, err = dirSize(fname)
if err != nil {
return err
}
}
fmt.Fprintf(os.Stderr,
"Sending %s %s named '%s'\nCode is: %s\nOn the other computer, please run:\n\ncroc %s\n\n",
humanize.Bytes(uint64(fsize)),
fileOrFolder,
filename,
codePhrase,
codePhrase,
)
return cr.Send(fname, codePhrase)
}
func receive(c *cli.Context) error {
if c.GlobalString("code") != "" {
codePhrase = c.GlobalString("code")
}
if c.Args().First() != "" {
codePhrase = c.Args().First()
}
if codePhrase == "" {
codePhrase = utils.GetInput("Enter receive code: ")
}
return cr.Receive(codePhrase)
}
func relay(c *cli.Context) error {
return cr.Relay()
}
func dirSize(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if !info.IsDir() {
size += info.Size()
}
return err
})
return size, err
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)
}

718
src/cli/cli.go Normal file
View File

@ -0,0 +1,718 @@
package cli
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/chzyer/readline"
"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/pake/v3"
)
// Version specifies the version
var Version string
// Run will run the command line program
func Run() (err error) {
// use all of the processors
runtime.GOMAXPROCS(runtime.NumCPU())
app := cli.NewApp()
app.Name = "croc"
if Version == "" {
Version = "v10.1.0"
}
app.Version = Version
app.Compiled = time.Now()
app.Usage = "easily and securely transfer stuff from one computer to another"
app.UsageText = `croc [GLOBAL OPTIONS] [COMMAND] [COMMAND OPTIONS] [filename(s) or folder]
USAGE EXAMPLES:
Send a file:
croc send file.txt
-git to respect your .gitignore
Send multiple files:
croc send file1.txt file2.txt file3.txt
or
croc send *.jpg
Send everything in a folder:
croc send example-folder-name
Send a file with a custom code:
croc send --code secret-code file.txt
Receive a file using code:
croc secret-code`
app.Commands = []*cli.Command{
{
Name: "send",
Usage: "send file(s), or folder (see options with croc send -h)",
Description: "send file(s), or folder, over the relay",
ArgsUsage: "[filename(s) or folder]",
Flags: []cli.Flag{
&cli.BoolFlag{Name: "zip", Usage: "zip folder before sending"},
&cli.StringFlag{Name: "code", Aliases: []string{"c"}, Usage: "codephrase used to connect to relay"},
&cli.StringFlag{Name: "hash", Value: "xxhash", Usage: "hash algorithm (xxhash, imohash, md5)"},
&cli.StringFlag{Name: "text", Aliases: []string{"t"}, Usage: "send some text"},
&cli.BoolFlag{Name: "no-local", Usage: "disable local relay when sending"},
&cli.BoolFlag{Name: "no-multi", Usage: "disable multiplexing"},
&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,
},
{
Name: "relay",
Usage: "start your own relay (optional)",
Description: "start relay",
HelpName: "croc relay",
Action: relay,
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"},
},
},
}
app.Flags = []cli.Flag{
&cli.BoolFlag{Name: "internal-dns", Usage: "use a built-in DNS stub resolver rather than the host operating system"},
&cli.BoolFlag{Name: "classic", Usage: "toggle between the classic mode (insecure due to local attack vector) and new mode (secure)"},
&cli.BoolFlag{Name: "remember", Usage: "save these settings to reuse next time"},
&cli.BoolFlag{Name: "debug", Usage: "toggle debug mode"},
&cli.BoolFlag{Name: "yes", Usage: "automatically agree to all prompts"},
&cli.BoolFlag{Name: "stdout", Usage: "redirect file to stdout"},
&cli.BoolFlag{Name: "no-compress", Usage: "disable compression"},
&cli.BoolFlag{Name: "ask", Usage: "make sure sender and recipient are prompted"},
&cli.BoolFlag{Name: "local", Usage: "force to use only local connections"},
&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"}},
&cli.StringFlag{Name: "relay6", Value: models.DEFAULT_RELAY6, Usage: "ipv6 address of the relay", EnvVars: []string{"CROC_RELAY6"}},
&cli.StringFlag{Name: "out", Value: ".", Usage: "specify an output folder to receive the file"},
&cli.StringFlag{Name: "pass", Value: models.DEFAULT_PASSPHRASE, Usage: "password for the relay", EnvVars: []string{"CROC_PASS"}},
&cli.StringFlag{Name: "socks5", Value: "", Usage: "add a socks5 proxy", EnvVars: []string{"SOCKS5_PROXY"}},
&cli.StringFlag{Name: "connect", Value: "", Usage: "add a http proxy", EnvVars: []string{"HTTP_PROXY"}},
&cli.StringFlag{Name: "throttleUpload", Value: "", Usage: "Throttle the upload speed e.g. 500k"},
}
app.EnableBashCompletion = true
app.HideHelp = false
app.HideVersion = false
app.Action = func(c *cli.Context) error {
allStringsAreFiles := func(strs []string) bool {
for _, str := range strs {
if !utils.Exists(str) {
return false
}
}
return true
}
// check if "classic" is set
classicFile := getClassicConfigFile(true)
classicInsecureMode := utils.Exists(classicFile)
if c.Bool("classic") {
if classicInsecureMode {
// classic mode not enabled
fmt.Print(`Classic mode is currently ENABLED.
Disabling this mode will prevent the shared secret from being visible
on the host's process list when passed via the command line. On a
multi-user system, this will help ensure that other local users cannot
access the shared secret and receive the files instead of the intended
recipient.
Do you wish to continue to DISABLE the classic mode? (y/N) `)
choice := strings.ToLower(utils.GetInput(""))
if choice == "y" || choice == "yes" {
os.Remove(classicFile)
fmt.Print("\nClassic mode DISABLED.\n\n")
fmt.Print(`To send and receive, export the CROC_SECRET variable with the code phrase:
Send: CROC_SECRET=*** croc send file.txt
Receive: CROC_SECRET=*** croc` + "\n\n")
} else {
fmt.Print("\nClassic mode ENABLED.\n")
}
} else {
// enable classic mode
// touch the file
fmt.Print(`Classic mode is currently DISABLED.
Please note that enabling this mode will make the shared secret visible
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) `)
choice := strings.ToLower(utils.GetInput(""))
if choice == "y" || choice == "yes" {
fmt.Print("\nClassic mode ENABLED.\n\n")
os.WriteFile(classicFile, []byte("enabled"), 0o644)
fmt.Print(`To send and receive, use the code phrase:
Send: croc send --code *** file.txt
Receive: croc ***` + "\n\n")
} else {
fmt.Print("\nClassic mode DISABLED.\n")
}
}
os.Exit(0)
}
// if trying to send but forgot send, let the user know
if c.Args().Present() && allStringsAreFiles(c.Args().Slice()) {
fnames := []string{}
for _, fpath := range c.Args().Slice() {
_, basename := filepath.Split(fpath)
fnames = append(fnames, "'"+basename+"'")
}
promptMessage := fmt.Sprintf("Did you mean to send %s? (Y/n) ", strings.Join(fnames, ", "))
choice := strings.ToLower(utils.GetInput(promptMessage))
if choice == "" || choice == "y" || choice == "yes" {
return send(c)
}
}
return receive(c)
}
return app.Run(os.Args)
}
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")
}
}
func getSendConfigFile(requireValidPath bool) string {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
log.Error(err)
return ""
}
return path.Join(configFile, "send.json")
}
func getClassicConfigFile(requireValidPath bool) string {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
log.Error(err)
return ""
}
return path.Join(configFile, "classic_enabled")
}
func getReceiveConfigFile(requireValidPath bool) (string, error) {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
log.Error(err)
return "", err
}
return path.Join(configFile, "receive.json"), nil
}
func determinePass(c *cli.Context) (pass string) {
pass = c.String("pass")
b, err := os.ReadFile(pass)
if err == nil {
pass = strings.TrimSpace(string(b))
}
return
}
func send(c *cli.Context) (err error) {
setDebugLevel(c)
comm.Socks5Proxy = c.String("socks5")
comm.HttpProxy = c.String("connect")
portParam := c.Int("port")
if portParam == 0 {
portParam = 9009
}
transfersParam := c.Int("transfers")
if transfersParam == 0 {
transfersParam = 4
}
ports := make([]string, transfersParam+1)
for i := 0; i <= transfersParam; i++ {
ports[i] = strconv.Itoa(portParam + i)
}
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"),
ShowQrCode: c.Bool("qrcode"),
MulticastAddress: c.String("multicast"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
} else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 {
crocOptions.RelayAddress = ""
}
b, errOpen := os.ReadFile(getSendConfigFile(false))
if errOpen == nil && !c.Bool("remember") {
var rememberedOptions croc.Options
err = json.Unmarshal(b, &rememberedOptions)
if err != nil {
log.Error(err)
return
}
// update anything that isn't explicitly set
if !c.IsSet("relay") && rememberedOptions.RelayAddress != "" {
crocOptions.RelayAddress = rememberedOptions.RelayAddress
}
if !c.IsSet("no-local") {
crocOptions.DisableLocal = rememberedOptions.DisableLocal
}
if !c.IsSet("ports") && len(rememberedOptions.RelayPorts) > 0 {
crocOptions.RelayPorts = rememberedOptions.RelayPorts
}
if !c.IsSet("code") {
crocOptions.SharedSecret = rememberedOptions.SharedSecret
}
if !c.IsSet("pass") && rememberedOptions.RelayPassword != "" {
crocOptions.RelayPassword = rememberedOptions.RelayPassword
}
if !c.IsSet("relay6") && rememberedOptions.RelayAddress6 != "" {
crocOptions.RelayAddress6 = rememberedOptions.RelayAddress6
}
if !c.IsSet("overwrite") {
crocOptions.Overwrite = rememberedOptions.Overwrite
}
if !c.IsSet("curve") && rememberedOptions.Curve != "" {
crocOptions.Curve = rememberedOptions.Curve
}
if !c.IsSet("local") {
crocOptions.OnlyLocal = rememberedOptions.OnlyLocal
}
if !c.IsSet("hash") {
crocOptions.HashAlgorithm = rememberedOptions.HashAlgorithm
}
if !c.IsSet("git") {
crocOptions.GitIgnore = rememberedOptions.GitIgnore
}
}
var fnames []string
stat, _ := os.Stdin.Stat()
if ((stat.Mode() & os.ModeCharDevice) == 0) && !c.Bool("ignore-stdin") {
fnames, err = getStdin()
if err != nil {
return
}
utils.MarkFileForRemoval(fnames[0])
defer func() {
e := os.Remove(fnames[0])
if e != nil {
log.Error(e)
}
}()
} else if c.String("text") != "" {
fnames, err = makeTempFileWithString(c.String("text"))
if err != nil {
return
}
utils.MarkFileForRemoval(fnames[0])
defer func() {
e := os.Remove(fnames[0])
if e != nil {
log.Error(e)
}
}()
} else {
fnames = c.Args().Slice()
}
if len(fnames) == 0 {
return errors.New("must specify file: croc send [filename(s) or folder]")
}
classicInsecureMode := utils.Exists(getClassicConfigFile(true))
if !classicInsecureMode {
// if operating system is UNIX, then use environmental variable to set the code
if (!(runtime.GOOS == "windows") && c.IsSet("code")) || os.Getenv("CROC_SECRET") != "" {
crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
if crocOptions.SharedSecret == "" {
fmt.Printf(`On UNIX systems, to send with a custom code phrase,
you need to set the environmental variable CROC_SECRET:
CROC_SECRET=**** croc send file.txt
Or you can have the code phrase automatically generated:
croc send file.txt
Or you can go back to the classic croc behavior by enabling classic mode:
croc --classic
`)
os.Exit(0)
}
}
}
if len(crocOptions.SharedSecret) == 0 {
// generate code phrase
crocOptions.SharedSecret = utils.GetRandomName()
}
minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders, err := croc.GetFilesInfo(fnames, crocOptions.ZipFolder, crocOptions.GitIgnore)
if err != nil {
return
}
cr, err := croc.New(crocOptions)
if err != nil {
return
}
// save the config
saveConfig(c, crocOptions)
err = cr.Send(minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders)
return
}
func getStdin() (fnames []string, err error) {
f, err := os.CreateTemp(".", "croc-stdin-")
if err != nil {
return
}
_, err = io.Copy(f, os.Stdin)
if err != nil {
return
}
err = f.Close()
if err != nil {
return
}
fnames = []string{f.Name()}
return
}
func makeTempFileWithString(s string) (fnames []string, err error) {
f, err := os.CreateTemp(".", "croc-stdin-")
if err != nil {
return
}
_, err = f.WriteString(s)
if err != nil {
return
}
err = f.Close()
if err != nil {
return
}
fnames = []string{f.Name()}
return
}
func saveConfig(c *cli.Context, crocOptions croc.Options) {
if c.Bool("remember") {
configFile := getSendConfigFile(true)
log.Debug("saving config file")
var bConfig []byte
// if the code wasn't set, don't save it
if c.String("code") == "" {
crocOptions.SharedSecret = ""
}
bConfig, err := json.MarshalIndent(crocOptions, "", " ")
if err != nil {
log.Error(err)
return
}
err = os.WriteFile(configFile, bConfig, 0o644)
if err != nil {
log.Error(err)
return
}
log.Debugf("wrote %s", configFile)
}
}
type TabComplete struct{}
func (t TabComplete) Do(line []rune, pos int) ([][]rune, int) {
var words = strings.SplitAfter(string(line), "-")
var lastPartialWord = words[len(words)-1]
var nbCharacter = len(lastPartialWord)
if nbCharacter == 0 {
// No completion
return [][]rune{[]rune("")}, 0
}
if len(words) == 1 && nbCharacter == utils.NbPinNumbers {
// Check if word is indeed a number
_, err := strconv.Atoi(lastPartialWord)
if err == nil {
return [][]rune{[]rune("-")}, nbCharacter
}
}
var strArray [][]rune
for _, s := range mnemonicode.WordList {
if strings.HasPrefix(s, lastPartialWord) {
var completionCandidate = s[nbCharacter:]
if len(words) <= mnemonicode.WordsRequired(utils.NbBytesWords) {
completionCandidate += "-"
}
strArray = append(strArray, []rune(completionCandidate))
}
}
return strArray, nbCharacter
}
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"),
MulticastAddress: c.String("multicast"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
} else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 {
crocOptions.RelayAddress = ""
}
switch c.Args().Len() {
case 1:
crocOptions.SharedSecret = c.Args().First()
case 3:
fallthrough
case 4:
var phrase []string
phrase = append(phrase, c.Args().First())
phrase = append(phrase, c.Args().Tail()...)
crocOptions.SharedSecret = strings.Join(phrase, "-")
}
// load options here
setDebugLevel(c)
doRemember := c.Bool("remember")
configFile, err := getReceiveConfigFile(doRemember)
if err != nil && doRemember {
return
}
b, errOpen := os.ReadFile(configFile)
if errOpen == nil && !doRemember {
var rememberedOptions croc.Options
err = json.Unmarshal(b, &rememberedOptions)
if err != nil {
log.Error(err)
return
}
// update anything that isn't explicitly Globally set
if !c.IsSet("relay") && rememberedOptions.RelayAddress != "" {
crocOptions.RelayAddress = rememberedOptions.RelayAddress
}
if !c.IsSet("yes") {
crocOptions.NoPrompt = rememberedOptions.NoPrompt
}
if crocOptions.SharedSecret == "" {
crocOptions.SharedSecret = rememberedOptions.SharedSecret
}
if !c.IsSet("pass") && rememberedOptions.RelayPassword != "" {
crocOptions.RelayPassword = rememberedOptions.RelayPassword
}
if !c.IsSet("relay6") && rememberedOptions.RelayAddress6 != "" {
crocOptions.RelayAddress6 = rememberedOptions.RelayAddress6
}
if !c.IsSet("overwrite") {
crocOptions.Overwrite = rememberedOptions.Overwrite
}
if !c.IsSet("curve") && rememberedOptions.Curve != "" {
crocOptions.Curve = rememberedOptions.Curve
}
if !c.IsSet("local") {
crocOptions.OnlyLocal = rememberedOptions.OnlyLocal
}
}
classicInsecureMode := utils.Exists(getClassicConfigFile(true))
if crocOptions.SharedSecret == "" && os.Getenv("CROC_SECRET") != "" {
crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
} else if !(runtime.GOOS == "windows") && crocOptions.SharedSecret != "" && !classicInsecureMode {
crocOptions.SharedSecret = os.Getenv("CROC_SECRET")
if crocOptions.SharedSecret == "" {
fmt.Printf(`On UNIX systems, to receive with croc you either need
to set a code phrase using your environmental variables:
CROC_SECRET=**** croc
Or you can specify the code phrase when you run croc without
declaring the secret on the command line:
croc
Enter receive code: ****
Or you can go back to the classic croc behavior by enabling classic mode:
croc --classic
`)
os.Exit(0)
}
}
if crocOptions.SharedSecret == "" {
l, err := readline.NewEx(&readline.Config{
Prompt: "Enter receive code: ",
AutoComplete: TabComplete{},
})
if err != nil {
return err
}
crocOptions.SharedSecret, err = l.Readline()
if err != nil {
return err
}
}
if c.String("out") != "" {
if err = os.Chdir(c.String("out")); err != nil {
return err
}
}
cr, err := croc.New(crocOptions)
if err != nil {
return
}
// save the config
if doRemember {
log.Debug("saving config file")
var bConfig []byte
bConfig, err = json.MarshalIndent(crocOptions, "", " ")
if err != nil {
log.Error(err)
return
}
err = os.WriteFile(configFile, bConfig, 0o644)
if err != nil {
log.Error(err)
return
}
log.Debugf("wrote %s", configFile)
}
err = cr.Receive()
return
}
func relay(c *cli.Context) (err error) {
log.Infof("starting croc relay version %v", Version)
debugString := "info"
if c.Bool("debug") {
debugString = "debug"
}
host := c.String("host")
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 {
continue
}
go func(portStr string) {
err := tcp.Run(debugString, host, portStr, determinePass(c))
if err != nil {
panic(err)
}
}(port)
}
return tcp.Run(debugString, host, ports[0], determinePass(c), tcpPorts)
}

View File

@ -2,119 +2,199 @@ package comm
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"net"
"strconv"
"net/url"
"strings"
"time"
"github.com/pkg/errors"
"github.com/magisterquis/connectproxy"
"github.com/schollz/croc/v10/src/utils"
log "github.com/schollz/logger"
"golang.org/x/net/proxy"
)
var Socks5Proxy = ""
var HttpProxy = ""
var MAGIC_BYTES = []byte("croc")
// Comm is some basic TCP communication
type Comm struct {
connection net.Conn
}
// NewConnection gets a new comm to a tcp address
func NewConnection(address string, timelimit ...time.Duration) (c *Comm, err error) {
tlimit := 30 * time.Second
if len(timelimit) > 0 {
tlimit = timelimit[0]
}
var connection net.Conn
if Socks5Proxy != "" && !utils.IsLocalIP(address) {
var dialer proxy.Dialer
// prepend schema if no schema is given
if !strings.Contains(Socks5Proxy, `://`) {
Socks5Proxy = `socks5://` + Socks5Proxy
}
socks5ProxyURL, urlParseError := url.Parse(Socks5Proxy)
if urlParseError != nil {
err = fmt.Errorf("unable to parse socks proxy url: %s", urlParseError)
log.Debug(err)
return
}
dialer, err = proxy.FromURL(socks5ProxyURL, proxy.Direct)
if err != nil {
err = fmt.Errorf("proxy failed: %w", err)
log.Debug(err)
return
}
log.Debug("dialing with dialer.Dial")
connection, err = dialer.Dial("tcp", address)
} else if HttpProxy != "" && !utils.IsLocalIP(address) {
var dialer proxy.Dialer
// prepend schema if no schema is given
if !strings.Contains(HttpProxy, `://`) {
HttpProxy = `http://` + HttpProxy
}
HttpProxyURL, urlParseError := url.Parse(HttpProxy)
if urlParseError != nil {
err = fmt.Errorf("unable to parse http proxy url: %s", urlParseError)
log.Debug(err)
return
}
dialer, err = connectproxy.New(HttpProxyURL, proxy.Direct)
if err != nil {
err = fmt.Errorf("proxy failed: %w", err)
log.Debug(err)
return
}
log.Debug("dialing with dialer.Dial")
connection, err = dialer.Dial("tcp", address)
} else {
log.Debugf("dialing to %s with timelimit %s", address, tlimit)
connection, err = net.DialTimeout("tcp", address, tlimit)
}
if err != nil {
err = fmt.Errorf("comm.NewConnection failed: %w", err)
log.Debug(err)
return
}
c = New(connection)
log.Debugf("connected to '%s'", address)
return
}
// New returns a new comm
func New(c net.Conn) Comm {
c.SetReadDeadline(time.Now().Add(3 * time.Hour))
c.SetDeadline(time.Now().Add(3 * time.Hour))
c.SetWriteDeadline(time.Now().Add(3 * time.Hour))
return Comm{c}
func New(c net.Conn) *Comm {
if err := c.SetReadDeadline(time.Now().Add(3 * time.Hour)); err != nil {
log.Warnf("error setting read deadline: %v", err)
}
if err := c.SetDeadline(time.Now().Add(3 * time.Hour)); err != nil {
log.Warnf("error setting overall deadline: %v", err)
}
if err := c.SetWriteDeadline(time.Now().Add(3 * time.Hour)); err != nil {
log.Errorf("error setting write deadline: %v", err)
}
comm := new(Comm)
comm.connection = c
return comm
}
// Connection returns the net.Conn connection
func (c Comm) Connection() net.Conn {
func (c *Comm) Connection() net.Conn {
return c.connection
}
// Close closes the connection
func (c Comm) Close() {
c.connection.Close()
}
func (c Comm) Write(b []byte) (int, error) {
tmpCopy := make([]byte, len(b)+5)
// Copy the buffer so it doesn't get changed while read by the recipient.
copy(tmpCopy[:5], []byte(fmt.Sprintf("%0.5d", len(b))))
copy(tmpCopy[5:], b)
n, err := c.connection.Write(tmpCopy)
if n != len(tmpCopy) {
if err != nil {
err = errors.Wrap(err, fmt.Sprintf("wanted to write %d but wrote %d", len(b), n))
} else {
err = fmt.Errorf("wanted to write %d but wrote %d", len(b), n)
}
func (c *Comm) Close() {
if err := c.connection.Close(); err != nil {
log.Warnf("error closing connection: %v", err)
}
// log.Printf("wanted to write %d but wrote %d", n, len(b))
return n, err
}
func (c Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
// read until we get 5 bytes
tmp := make([]byte, 5)
n, err := c.connection.Read(tmp)
func (c *Comm) Write(b []byte) (n int, err error) {
header := new(bytes.Buffer)
err = binary.Write(header, binary.LittleEndian, uint32(len(b)))
if err != nil {
fmt.Println("binary.Write failed:", err)
}
tmpCopy := append(header.Bytes(), b...)
tmpCopy = append(MAGIC_BYTES, tmpCopy...)
n, err = c.connection.Write(tmpCopy)
if err != nil {
err = fmt.Errorf("connection.Write failed: %w", err)
return
}
tmpCopy := make([]byte, n)
// Copy the buffer so it doesn't get changed while read by the recipient.
copy(tmpCopy, tmp[:n])
bs = tmpCopy
tmp = make([]byte, 1)
for {
// see if we have enough bytes
bs = bytes.Trim(bs, "\x00")
if len(bs) == 5 {
break
}
n, err := c.connection.Read(tmp)
if err != nil {
return nil, 0, nil, err
}
tmpCopy = make([]byte, n)
// Copy the buffer so it doesn't get changed while read by the recipient.
copy(tmpCopy, tmp[:n])
bs = append(bs, tmpCopy...)
if n != len(tmpCopy) {
err = fmt.Errorf("wanted to write %d but wrote %d", len(b), n)
return
}
return
}
numBytes, err = strconv.Atoi(strings.TrimLeft(string(bs), "0"))
func (c *Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
// long read deadline in case waiting for file
if err = c.connection.SetReadDeadline(time.Now().Add(3 * time.Hour)); err != nil {
log.Warnf("error setting read deadline: %v", err)
}
// must clear the timeout setting
defer c.connection.SetDeadline(time.Time{})
// read until we get 4 bytes for the magic
header := make([]byte, 4)
_, err = io.ReadFull(c.connection, header)
if err != nil {
return nil, 0, nil, err
log.Debugf("initial read error: %v", err)
return
}
buf = []byte{}
tmp = make([]byte, numBytes)
for {
n, err := c.connection.Read(tmp)
if err != nil {
return nil, 0, nil, err
}
tmpCopy = make([]byte, n)
// Copy the buffer so it doesn't get changed while read by the recipient.
copy(tmpCopy, tmp[:n])
buf = append(buf, bytes.TrimRight(tmpCopy, "\x00")...)
if len(buf) < numBytes {
// shrink the amount we need to read
tmp = tmp[:numBytes-len(buf)]
} else {
break
}
if !bytes.Equal(header, MAGIC_BYTES) {
err = fmt.Errorf("initial bytes are not magic: %x", header)
return
}
// read until we get 4 bytes for the header
header = make([]byte, 4)
_, err = io.ReadFull(c.connection, header)
if err != nil {
log.Debugf("initial read error: %v", err)
return
}
var numBytesUint32 uint32
rbuf := bytes.NewReader(header)
err = binary.Read(rbuf, binary.LittleEndian, &numBytesUint32)
if err != nil {
err = fmt.Errorf("binary.Read failed: %w", err)
log.Debug(err.Error())
return
}
numBytes = int(numBytesUint32)
// shorten the reading deadline in case getting weird data
if err = c.connection.SetReadDeadline(time.Now().Add(10 * time.Second)); err != nil {
log.Warnf("error setting read deadline: %v", err)
}
buf = make([]byte, numBytes)
_, err = io.ReadFull(c.connection, buf)
if err != nil {
log.Debugf("consecutive read error: %v", err)
return
}
// log.Printf("wanted %d and got %d", numBytes, len(buf))
return
}
// Send a message
func (c Comm) Send(message string) (err error) {
_, err = c.Write([]byte(message))
func (c *Comm) Send(message []byte) (err error) {
_, err = c.Write(message)
return
}
// Receive a message
func (c Comm) Receive() (s string, err error) {
b, _, _, err := c.Read()
s = string(b)
func (c *Comm) Receive() (b []byte, err error) {
b, _, _, err = c.Read()
return
}

66
src/comm/comm_test.go Normal file
View File

@ -0,0 +1,66 @@
package comm
import (
"crypto/rand"
"net"
"testing"
"time"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
func TestComm(t *testing.T) {
token := make([]byte, 3000)
if _, err := rand.Read(token); err != nil {
t.Error(err)
}
port := "8001"
go func() {
log.Debugf("starting TCP server on " + port)
server, err := net.Listen("tcp", "0.0.0.0:"+port)
if err != nil {
log.Error(err)
}
defer server.Close()
// spawn a new goroutine whenever a client connects
for {
connection, err := server.Accept()
if err != nil {
log.Error(err)
}
log.Debugf("client %s connected", connection.RemoteAddr().String())
go func(_ string, connection net.Conn) {
c := New(connection)
err = c.Send([]byte("hello, world"))
assert.Nil(t, err)
data, err := c.Receive()
assert.Nil(t, err)
assert.Equal(t, []byte("hello, computer"), data)
data, err = c.Receive()
assert.Nil(t, err)
assert.Equal(t, []byte{'\x00'}, data)
data, err = c.Receive()
assert.Nil(t, err)
assert.Equal(t, token, data)
}(port, connection)
}
}()
time.Sleep(300 * time.Millisecond)
a, err := NewConnection("127.0.0.1:"+port, 10*time.Minute)
assert.Nil(t, err)
data, err := a.Receive()
assert.Equal(t, []byte("hello, world"), data)
assert.Nil(t, err)
assert.Nil(t, a.Send([]byte("hello, computer")))
assert.Nil(t, a.Send([]byte{'\x00'}))
assert.Nil(t, a.Send(token))
_ = a.Connection()
a.Close()
assert.NotNil(t, a.Send(token))
_, err = a.Write(token)
assert.NotNil(t, err)
}

View File

@ -4,12 +4,21 @@ import (
"bytes"
"compress/flate"
"io"
log "github.com/schollz/logger"
)
// CompressWithOption returns compressed data using the specified level
func CompressWithOption(src []byte, level int) []byte {
compressedData := new(bytes.Buffer)
compress(src, compressedData, level)
return compressedData.Bytes()
}
// Compress returns a compressed byte slice.
func Compress(src []byte) []byte {
compressedData := new(bytes.Buffer)
compress(src, compressedData, 9)
compress(src, compressedData, -2)
return compressedData.Bytes()
}
@ -23,14 +32,22 @@ func Decompress(src []byte) []byte {
// compress uses flate to compress a byte slice to a corresponding level
func compress(src []byte, dest io.Writer, level int) {
compressor, _ := flate.NewWriter(dest, level)
compressor.Write(src)
compressor, err := flate.NewWriter(dest, level)
if err != nil {
log.Debugf("error level data: %v", err)
return
}
if _, err := compressor.Write(src); err != nil {
log.Debugf("error writing data: %v", err)
}
compressor.Close()
}
// compress uses flate to decompress an io.Reader
func decompress(src io.Reader, dest io.Writer) {
decompressor := flate.NewReader(src)
io.Copy(dest, decompressor)
if _, err := io.Copy(dest, decompressor); err != nil {
log.Debugf("error copying data: %v", err)
}
decompressor.Close()
}

View File

@ -0,0 +1,105 @@
package compress
import (
"crypto/rand"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
var fable = []byte(`The Frog and the Crocodile
Once, there was a frog who lived in the middle of a swamp. His entire family had lived in that swamp for generations, but this particular frog decided that he had had quite enough wetness to last him a lifetime. He decided that he was going to find a dry place to live instead.
The only thing that separated him from dry land was a swampy, muddy, swiftly flowing river. But the river was home to all sorts of slippery, slittering snakes that loved nothing better than a good, plump frog for dinner, so Frog didn't dare try to swim across.
So for many days, the frog stayed put, hopping along the bank, trying to think of a way to get across.
The snakes hissed and jeered at him, daring him to come closer, but he refused. Occasionally they would slither closer, jaws open to attack, but the frog always leaped out of the way. But no matter how far upstream he searched or how far downstream, the frog wasn't able to find a way across the water.
He had felt certain that there would be a bridge, or a place where the banks came together, yet all he found was more reeds and water. After a while, even the snakes stopped teasing him and went off in search of easier prey.
The frog sighed in frustration and sat to sulk in the rushes. Suddenly, he spotted two big eyes staring at him from the water. The giant log-shaped animal opened its mouth and asked him, "What are you doing, Frog? Surely there are enough flies right there for a meal."
The frog croaked in surprise and leaped away from the crocodile. That creature could swallow him whole in a moment without thinking about it! Once he was a satisfied that he was a safe distance away, he answered. "I'm tired of living in swampy waters, and I want to travel to the other side of the river. But if I swim across, the snakes will eat me."
The crocodile harrumphed in agreement and sat, thinking, for a while. "Well, if you're afraid of the snakes, I could give you a ride across," he suggested.
"Oh no, I don't think so," Frog answered quickly. "You'd eat me on the way over, or go underwater so the snakes could get me!"
"Now why would I let the snakes get you? I think they're a terrible nuisance with all their hissing and slithering! The river would be much better off without them altogether! Anyway, if you're so worried that I might eat you, you can ride on my tail."
The frog considered his offer. He did want to get to dry ground very badly, and there didn't seem to be any other way across the river. He looked at the crocodile from his short, squat buggy eyes and wondered about the crocodile's motives. But if he rode on the tail, the croc couldn't eat him anyway. And he was right about the snakes--no self-respecting crocodile would give a meal to the snakes.
"Okay, it sounds like a good plan to me. Turn around so I can hop on your tail."
The crocodile flopped his tail into the marshy mud and let the frog climb on, then he waddled out to the river. But he couldn't stick his tail into the water as a rudder because the frog was on it -- and if he put his tail in the water, the snakes would eat the frog. They clumsily floated downstream for a ways, until the crocodile said, "Hop onto my back so I can steer straight with my tail." The frog moved, and the journey smoothed out.
From where he was sitting, the frog couldn't see much except the back of Crocodile's head. "Why don't you hop up on my head so you can see everything around us?" Crocodile invited. `)
func BenchmarkCompressLevelMinusTwo(b *testing.B) {
for i := 0; i < b.N; i++ {
CompressWithOption(fable, -2)
}
}
func BenchmarkCompressLevelNine(b *testing.B) {
for i := 0; i < b.N; i++ {
CompressWithOption(fable, 9)
}
}
func BenchmarkCompressLevelMinusTwoBinary(b *testing.B) {
data := make([]byte, 1000000)
if _, err := rand.Read(data); err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
CompressWithOption(data, -2)
}
}
func BenchmarkCompressLevelNineBinary(b *testing.B) {
data := make([]byte, 1000000)
if _, err := rand.Read(data); err != nil {
b.Fatal(err)
}
for i := 0; i < b.N; i++ {
CompressWithOption(data, 9)
}
}
func TestCompress(t *testing.T) {
compressedB := CompressWithOption(fable, 9)
dataRateSavings := 100 * (1.0 - float64(len(compressedB))/float64(len(fable)))
fmt.Printf("Level 9: %2.0f%% percent space savings\n", dataRateSavings)
assert.True(t, len(compressedB) < len(fable))
assert.Equal(t, fable, Decompress(compressedB))
compressedB = CompressWithOption(fable, -2)
dataRateSavings = 100 * (1.0 - float64(len(compressedB))/float64(len(fable)))
fmt.Printf("Level -2: %2.0f%% percent space savings\n", dataRateSavings)
assert.True(t, len(compressedB) < len(fable))
compressedB = Compress(fable)
dataRateSavings = 100 * (1.0 - float64(len(compressedB))/float64(len(fable)))
fmt.Printf("Level -2: %2.0f%% percent space savings\n", dataRateSavings)
assert.True(t, len(compressedB) < len(fable))
data := make([]byte, 4096)
if _, err := rand.Read(data); err != nil {
t.Fatal(err)
}
compressedB = CompressWithOption(data, -2)
dataRateSavings = 100 * (1.0 - float64(len(compressedB))/float64(len(data)))
fmt.Printf("random, Level -2: %2.0f%% percent space savings\n", dataRateSavings)
if _, err := rand.Read(data); err != nil {
t.Fatal(err)
}
compressedB = CompressWithOption(data, 9)
dataRateSavings = 100 * (1.0 - float64(len(compressedB))/float64(len(data)))
fmt.Printf("random, Level 9: %2.0f%% percent space savings\n", dataRateSavings)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,81 +1,400 @@
package croc
import (
"crypto/rand"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
"time"
"github.com/schollz/croc/src/utils"
"github.com/schollz/croc/v10/src/tcp"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
func sendAndReceive(t *testing.T, forceSend int, local bool) {
room := utils.GetRandomName()
var startTime time.Time
var durationPerMegabyte float64
megabytes := 1
if local {
megabytes = 100
func init() {
log.SetLevel("trace")
go tcp.Run("debug", "127.0.0.1", "8281", "pass123", "8282,8283,8284,8285")
go tcp.Run("debug", "127.0.0.1", "8282", "pass123")
go tcp.Run("debug", "127.0.0.1", "8283", "pass123")
go tcp.Run("debug", "127.0.0.1", "8284", "pass123")
go tcp.Run("debug", "127.0.0.1", "8285", "pass123")
time.Sleep(1 * time.Second)
}
func TestCrocReadme(t *testing.T) {
defer os.Remove("README.md")
log.Debug("setting up sender")
sender, err := New(Options{
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
}
fname := generateRandomFile(megabytes)
log.Debug("setting up receiver")
receiver, err := New(Options{
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
})
if err != nil {
panic(err)
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
c := Init(true)
c.NoLocal = !local
// c.AddressTCPPorts = []string{"8154", "8155"}
c.ForceSend = forceSend
c.UseCompression = true
c.UseEncryption = true
assert.Nil(t, c.Send(fname, room))
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../README.md"}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
err := sender.Send(filesInfo, emptyFolders, totalNumberFolders)
if err != nil {
t.Errorf("send failed: %v", err)
}
wg.Done()
}()
time.Sleep(100 * time.Millisecond)
go func() {
defer wg.Done()
time.Sleep(5 * time.Second)
os.MkdirAll("test", 0755)
os.Chdir("test")
c := Init(true)
c.NoLocal = !local
// c.AddressTCPPorts = []string{"8154", "8155"}
c.ForceSend = forceSend
startTime = time.Now()
assert.Nil(t, c.Receive(room))
durationPerMegabyte = float64(megabytes) / time.Since(startTime).Seconds()
assert.True(t, utils.Exists(fname))
err := receiver.Receive()
if err != nil {
t.Errorf("receive failed: %v", err)
}
wg.Done()
}()
wg.Wait()
os.Chdir("..")
os.RemoveAll("test")
os.Remove(fname)
fmt.Printf("\n-----\n%2.1f MB/s\n----\n", durationPerMegabyte)
}
func TestSendReceivePubWebsockets(t *testing.T) {
sendAndReceive(t, 1, false)
func TestCrocEmptyFolder(t *testing.T) {
pathName := "../../testEmpty"
defer os.RemoveAll(pathName)
defer os.RemoveAll("./testEmpty")
os.MkdirAll(pathName, 0o755)
log.Debug("setting up sender")
sender, err := New(Options{
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
})
if err != nil {
panic(err)
}
log.Debug("setting up receiver")
receiver, err := New(Options{
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
})
if err != nil {
panic(err)
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{pathName}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
err := sender.Send(filesInfo, emptyFolders, totalNumberFolders)
if err != nil {
t.Errorf("send failed: %v", err)
}
wg.Done()
}()
time.Sleep(100 * time.Millisecond)
go func() {
err := receiver.Receive()
if err != nil {
t.Errorf("receive failed: %v", err)
}
wg.Done()
}()
wg.Wait()
}
func TestSendReceivePubTCP(t *testing.T) {
sendAndReceive(t, 2, false)
func TestCrocSymlink(t *testing.T) {
pathName := "../link-in-folder"
defer os.RemoveAll(pathName)
defer os.RemoveAll("./link-in-folder")
os.MkdirAll(pathName, 0o755)
os.Symlink("../../README.md", filepath.Join(pathName, "README.link"))
log.Debug("setting up sender")
sender, err := New(Options{
IsSender: true,
SharedSecret: "8124-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
}
log.Debug("setting up receiver")
receiver, err := New(Options{
IsSender: false,
SharedSecret: "8124-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
})
if err != nil {
panic(err)
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{pathName}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
err = sender.Send(filesInfo, emptyFolders, totalNumberFolders)
if err != nil {
t.Errorf("send failed: %v", err)
}
wg.Done()
}()
time.Sleep(100 * time.Millisecond)
go func() {
err = receiver.Receive()
if err != nil {
t.Errorf("receive failed: %v", err)
}
wg.Done()
}()
wg.Wait()
s, err := filepath.EvalSymlinks(path.Join(pathName, "README.link"))
if s != "../../README.md" && s != "..\\..\\README.md" {
log.Debug(s)
t.Errorf("symlink failed to transfer in folder")
}
if err != nil {
t.Errorf("symlink transfer failed: %s", err.Error())
}
}
func TestCrocIgnoreGit(t *testing.T) {
log.SetLevel("trace")
defer os.Remove(".gitignore")
time.Sleep(300 * time.Millisecond)
time.Sleep(1 * time.Second)
file, err := os.Create(".gitignore")
if err != nil {
log.Errorf("error creating file")
}
_, err = file.WriteString("LICENSE")
if err != nil {
log.Errorf("error writing to file")
}
time.Sleep(1 * time.Second)
// due to how files are ignored in this function, all we have to do to test is make sure LICENSE doesn't get included in FilesInfo.
filesInfo, _, _, errGet := GetFilesInfo([]string{"../../LICENSE", ".gitignore", "croc.go"}, false, true)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
for _, file := range filesInfo {
if strings.Contains(file.Name, "LICENSE") {
t.Errorf("test failed, should ignore LICENSE")
}
}
}
func TestSendReceiveLocalWebsockets(t *testing.T) {
sendAndReceive(t, 1, true)
func TestCrocLocal(t *testing.T) {
log.SetLevel("trace")
defer os.Remove("LICENSE")
defer os.Remove("touched")
time.Sleep(300 * time.Millisecond)
log.Debug("setting up sender")
sender, err := New(Options{
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8181",
RelayPorts: []string{"8181", "8182"},
RelayPassword: "pass123",
Stdout: true,
NoPrompt: true,
DisableLocal: false,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
}
time.Sleep(1 * time.Second)
log.Debug("setting up receiver")
receiver, err := New(Options{
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "127.0.0.1:8181",
RelayPassword: "pass123",
Stdout: true,
NoPrompt: true,
DisableLocal: false,
Curve: "siec",
Overwrite: true,
})
if err != nil {
panic(err)
}
var wg sync.WaitGroup
os.Create("touched")
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../LICENSE", "touched"}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
err := sender.Send(filesInfo, emptyFolders, totalNumberFolders)
if err != nil {
t.Errorf("send failed: %v", err)
}
wg.Done()
}()
time.Sleep(100 * time.Millisecond)
go func() {
err := receiver.Receive()
if err != nil {
t.Errorf("send failed: %v", err)
}
wg.Done()
}()
wg.Wait()
}
// func TestSendReceiveLocalTCP(t *testing.T) {
// sendAndReceive(t, 2, true)
// }
func TestCrocError(t *testing.T) {
content := []byte("temporary file's content")
tmpfile, err := os.CreateTemp("", "example")
if err != nil {
panic(err)
}
func generateRandomFile(megabytes int) (fname string) {
// generate a random file
bigBuff := make([]byte, 1024*1024*megabytes)
rand.Read(bigBuff)
fname = fmt.Sprintf("%dmb.file", megabytes)
ioutil.WriteFile(fname, bigBuff, 0666)
return
defer os.Remove(tmpfile.Name()) // clean up
if _, err = tmpfile.Write(content); err != nil {
panic(err)
}
if err = tmpfile.Close(); err != nil {
panic(err)
}
Debug(false)
log.SetLevel("warn")
sender, _ := New(Options{
IsSender: true,
SharedSecret: "8123-testingthecroc2",
Debug: true,
RelayAddress: "doesntexistok.com:8381",
RelayPorts: []string{"8381", "8382"},
RelayPassword: "pass123",
Stdout: true,
NoPrompt: true,
DisableLocal: true,
Curve: "siec",
Overwrite: true,
})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{tmpfile.Name()}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
err = sender.Send(filesInfo, emptyFolders, totalNumberFolders)
log.Debug(err)
assert.NotNil(t, err)
}
func TestCleanUp(t *testing.T) {
// windows allows files to be deleted only if they
// are not open by another program so the remove actions
// from the above tests will not always do a good clean up
// This "test" will make sure
operatingSystem := runtime.GOOS
log.Debugf("The operating system is %s", operatingSystem)
if operatingSystem == "windows" {
time.Sleep(1 * time.Second)
log.Debug("Full cleanup")
var err error
for _, file := range []string{"README.md", "./README.md"} {
err = os.Remove(file)
if err == nil {
log.Debugf("Successfully purged %s", file)
} else {
log.Debugf("%s was already purged.", file)
}
}
for _, folder := range []string{"./testEmpty", "./link-in-folder"} {
err = os.RemoveAll(folder)
if err == nil {
log.Debugf("Successfully purged %s", folder)
} else {
log.Debugf("%s was already purged.", folder)
}
}
}
}

View File

@ -1,203 +0,0 @@
package croc
import (
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"strings"
"time"
log "github.com/cihub/seelog"
"github.com/gorilla/websocket"
"github.com/schollz/croc/src/recipient"
"github.com/schollz/croc/src/relay"
"github.com/schollz/croc/src/sender"
"github.com/schollz/peerdiscovery"
"github.com/schollz/utils"
)
// Send the file
func (c *Croc) Send(fname, codephrase string) (err error) {
log.Debugf("sending %s", fname)
errChan := make(chan error)
// normally attempt two connections
waitingFor := 2
// use public relay
if !c.LocalOnly {
go func() {
// atttempt to connect to public relay
errChan <- c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, fname, codephrase, true, false)
}()
} else {
waitingFor = 1
}
// use local relay
if !c.NoLocal {
go func() {
// start own relay and connect to it
go relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
time.Sleep(250 * time.Millisecond) // race condition here, but this should work most of the time :(
// broadcast for peer discovery
go func() {
log.Debug("starting local discovery...")
discovered, err := peerdiscovery.Discover(peerdiscovery.Settings{
Limit: 1,
TimeLimit: 600 * time.Second,
Delay: 50 * time.Millisecond,
Payload: []byte(c.RelayWebsocketPort + "- " + strings.Join(c.RelayTCPPorts, ",")),
})
log.Debug(discovered, err)
}()
// connect to own relay
errChan <- c.sendReceive("localhost", c.RelayWebsocketPort, c.RelayTCPPorts, fname, codephrase, true, true)
}()
} else {
waitingFor = 1
}
err = <-errChan
if err == nil || waitingFor == 1 {
log.Debug("returning")
return
}
log.Debug(err)
return <-errChan
}
// Receive the file
func (c *Croc) Receive(codephrase string) (err error) {
log.Debug("receiving")
// use local relay first
if !c.NoLocal {
log.Debug("trying discovering")
// try to discovery codephrase and server through peer network
discovered, errDiscover := peerdiscovery.Discover(peerdiscovery.Settings{
Limit: 1,
TimeLimit: 300 * time.Millisecond,
Delay: 50 * time.Millisecond,
Payload: []byte("checking"),
AllowSelf: true,
DisableBroadcast: true,
})
log.Debug("finished")
log.Debug(discovered)
if errDiscover != nil {
log.Debug(errDiscover)
}
if len(discovered) > 0 {
if discovered[0].Address == utils.GetLocalIP() {
discovered[0].Address = "localhost"
}
log.Debugf("discovered %s:%s", discovered[0].Address, discovered[0].Payload)
// see if we can actually connect to it
timeout := time.Duration(200 * time.Millisecond)
client := http.Client{
Timeout: timeout,
}
ports := strings.Split(string(discovered[0].Payload), "-")
if len(ports) != 2 {
return errors.New("bad payload")
}
resp, err := client.Get(fmt.Sprintf("http://%s:%s/", discovered[0].Address, ports[0]))
if err == nil {
if resp.StatusCode == http.StatusOK {
// we connected, so use this
return c.sendReceive(discovered[0].Address, strings.TrimSpace(ports[0]), strings.Split(strings.TrimSpace(ports[1]), ","), "", codephrase, false, true)
}
} else {
log.Debugf("could not connect: %s", err.Error())
}
} else {
log.Debug("discovered no peers")
}
}
// use public relay
if !c.LocalOnly {
log.Debug("using public relay")
return c.sendReceive(c.Address, c.AddressWebsocketPort, c.AddressTCPPorts, "", codephrase, false, false)
}
return errors.New("must use local or public relay")
}
func (c *Croc) sendReceive(address, websocketPort string, tcpPorts []string, fname string, codephrase string, isSender bool, isLocal bool) (err error) {
defer log.Flush()
if len(codephrase) < 4 {
return fmt.Errorf("codephrase is too short")
}
// allow interrupts from Ctl+C
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
done := make(chan struct{})
// connect to server
websocketAddress := ""
if len(websocketPort) > 0 {
websocketAddress = fmt.Sprintf("ws://%s:%s/ws?room=%s", address, websocketPort, codephrase[:3])
} else {
websocketAddress = fmt.Sprintf("ws://%s/ws?room=%s", address, codephrase[:3])
}
log.Debugf("connecting to %s", websocketAddress)
sock, _, err := websocket.DefaultDialer.Dial(websocketAddress, nil)
if err != nil {
return
}
defer sock.Close()
// tell the websockets we are connected
err = sock.WriteMessage(websocket.BinaryMessage, []byte("connected"))
if err != nil {
return err
}
if isSender {
go sender.Send(c.ForceSend, address, tcpPorts, isLocal, done, sock, fname, codephrase, c.UseCompression, c.UseEncryption)
} else {
go recipient.Receive(c.ForceSend, address, tcpPorts, isLocal, done, sock, codephrase, c.NoRecipientPrompt, c.Stdout)
}
for {
select {
case <-done:
return nil
case <-interrupt:
if !c.Debug {
SetDebugLevel("critical")
}
log.Debug("interrupt")
err = sock.WriteMessage(websocket.TextMessage, []byte("interrupt"))
if err != nil {
return err
}
time.Sleep(50 * time.Millisecond)
// Cleanly close the connection by sending a close message and then
// waiting (with timeout) for the server to close the connection.
err := sock.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
if err != nil {
log.Debug("write close:", err)
return nil
}
select {
case <-done:
case <-time.After(100 * time.Millisecond):
}
return nil
}
}
}
// Relay will start a relay on the specified port
func (c *Croc) Relay() (err error) {
return relay.Run(c.RelayWebsocketPort, c.RelayTCPPorts)
}

View File

@ -5,85 +5,121 @@ import (
"crypto/cipher"
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"errors"
"strings"
"fmt"
"log"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/pbkdf2"
)
// Encryption stores the data
type Encryption struct {
Encrypted []byte `json:"e"`
Salt []byte `json:"s"`
IV []byte `json:"i"`
}
func (e Encryption) Bytes() []byte {
return []byte(base64.StdEncoding.EncodeToString(e.Encrypted) + "-" + base64.StdEncoding.EncodeToString(e.Salt) + "-" + base64.StdEncoding.EncodeToString(e.IV))
}
func FromBytes(b []byte) (enc Encryption, err error) {
enc = Encryption{}
items := strings.Split(string(b), "-")
if len(items) != 3 {
err = errors.New("not valid")
// New generates a new key based on a passphrase and salt
func New(passphrase []byte, usersalt []byte) (key []byte, salt []byte, err error) {
if len(passphrase) < 1 {
err = fmt.Errorf("need more than that for passphrase")
return
}
enc.Encrypted, err = base64.StdEncoding.DecodeString(items[0])
if err != nil {
return
}
enc.Salt, err = base64.StdEncoding.DecodeString(items[1])
if err != nil {
return
}
enc.IV, err = base64.StdEncoding.DecodeString(items[2])
return
}
// Encrypt will generate an encryption
func Encrypt(plaintext []byte, passphrase []byte, dontencrypt ...bool) Encryption {
if len(dontencrypt) > 0 && dontencrypt[0] {
return Encryption{
Encrypted: plaintext,
Salt: []byte("salt"),
IV: []byte("iv"),
}
}
key, saltBytes := deriveKey(passphrase, nil)
ivBytes := make([]byte, 12)
// http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
// Section 8.2
rand.Read(ivBytes)
b, _ := aes.NewCipher(key)
aesgcm, _ := cipher.NewGCM(b)
encrypted := aesgcm.Seal(nil, ivBytes, plaintext, nil)
return Encryption{
Encrypted: encrypted,
Salt: saltBytes,
IV: ivBytes,
}
}
// Decrypt an encryption
func (e Encryption) Decrypt(passphrase []byte, dontencrypt ...bool) (plaintext []byte, err error) {
if len(dontencrypt) > 0 && dontencrypt[0] {
return e.Encrypted, nil
}
key, _ := deriveKey(passphrase, e.Salt)
b, _ := aes.NewCipher(key)
aesgcm, _ := cipher.NewGCM(b)
plaintext, err = aesgcm.Open(nil, e.IV, e.Encrypted, nil)
return
}
func deriveKey(passphrase []byte, salt []byte) ([]byte, []byte) {
if salt == nil {
if usersalt == nil {
salt = make([]byte, 8)
// http://www.ietf.org/rfc/rfc2898.txt
// Salt.
rand.Read(salt)
if _, err := rand.Read(salt); err != nil {
log.Fatalf("can't get random salt: %v", err)
}
} else {
salt = usersalt
}
return pbkdf2.Key([]byte(passphrase), salt, 100, 32, sha256.New), salt
key = pbkdf2.Key(passphrase, salt, 100, 32, sha256.New)
return
}
// Encrypt will encrypt using the pre-generated key
func Encrypt(plaintext []byte, key []byte) (encrypted []byte, err error) {
// generate a random iv each time
// http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
// Section 8.2
ivBytes := make([]byte, 12)
if _, err = rand.Read(ivBytes); err != nil {
log.Fatalf("can't initialize crypto: %v", err)
}
b, err := aes.NewCipher(key)
if err != nil {
return
}
aesgcm, err := cipher.NewGCM(b)
if err != nil {
return
}
encrypted = aesgcm.Seal(nil, ivBytes, plaintext, nil)
encrypted = append(ivBytes, encrypted...)
return
}
// Decrypt using the pre-generated key
func Decrypt(encrypted []byte, key []byte) (plaintext []byte, err error) {
if len(encrypted) < 13 {
err = fmt.Errorf("incorrect passphrase")
return
}
b, err := aes.NewCipher(key)
if err != nil {
return
}
aesgcm, err := cipher.NewGCM(b)
if err != nil {
return
}
plaintext, err = aesgcm.Open(nil, encrypted[:12], encrypted[12:], nil)
return
}
// NewArgon2 generates a new key based on a passphrase and salt
// using argon2
// https://pkg.go.dev/golang.org/x/crypto/argon2
func NewArgon2(passphrase []byte, usersalt []byte) (aead cipher.AEAD, salt []byte, err error) {
if len(passphrase) < 1 {
err = fmt.Errorf("need more than that for passphrase")
return
}
if usersalt == nil {
salt = make([]byte, 8)
// http://www.ietf.org/rfc/rfc2898.txt
// Salt.
if _, err = rand.Read(salt); err != nil {
log.Fatalf("can't get random salt: %v", err)
}
} else {
salt = usersalt
}
aead, err = chacha20poly1305.NewX(argon2.IDKey(passphrase, salt, 1, 64*1024, 4, 32))
return
}
// EncryptChaCha will encrypt ChaCha20-Poly1305 using the pre-generated key
// https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
func EncryptChaCha(plaintext []byte, aead cipher.AEAD) (encrypted []byte, err error) {
nonce := make([]byte, aead.NonceSize(), aead.NonceSize()+len(plaintext)+aead.Overhead())
if _, err := rand.Read(nonce); err != nil {
panic(err)
}
// Encrypt the message and append the ciphertext to the nonce.
encrypted = aead.Seal(nonce, nonce, plaintext, nil)
return
}
// DecryptChaCha will encrypt ChaCha20-Poly1305 using the pre-generated key
// https://pkg.go.dev/golang.org/x/crypto/chacha20poly1305
func DecryptChaCha(encryptedMsg []byte, aead cipher.AEAD) (encrypted []byte, err error) {
if len(encryptedMsg) < aead.NonceSize() {
err = fmt.Errorf("ciphertext too short")
return
}
// Split nonce and ciphertext.
nonce, ciphertext := encryptedMsg[:aead.NonceSize()], encryptedMsg[aead.NonceSize():]
// Decrypt the message and check it wasn't tampered with.
encrypted, err = aead.Open(nil, nonce, ciphertext, nil)
return
}

View File

@ -1,41 +1,119 @@
package crypt
import "testing"
import (
"fmt"
"testing"
func BenchmarkEncryption(b *testing.B) {
"github.com/stretchr/testify/assert"
)
func BenchmarkEncrypt(b *testing.B) {
bob, _, _ := New([]byte("password"), nil)
for i := 0; i < b.N; i++ {
Encrypt([]byte(`
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse laoreet justo quis augue vehicula ornare. Nullam nec risus volutpat nulla dictum consectetur. Phasellus porttitor, justo non tincidunt finibus, massa justo iaculis urna, eget mattis nulla libero vitae risus. Vestibulum vehicula nunc id dignissim rutrum. Cras varius ac nulla a imperdiet. Sed finibus, libero in tempor hendrerit, turpis erat faucibus nisl, a consectetur massa mi eget mi. Vestibulum pulvinar lorem id ipsum elementum auctor.
Morbi at odio a eros eleifend faucibus. Sed at tempor urna, in interdum neque. Curabitur condimentum rhoncus orci, vel vulputate risus ultricies efficitur. Curabitur eu vehicula ligula. Curabitur suscipit ex vitae nunc faucibus vehicula. Mauris sed dictum mauris. Vivamus nec dui at urna porttitor suscipit. Integer ut eros finibus orci consectetur hendrerit id quis dolor. Proin dapibus orci quis massa viverra finibus. Sed quis ligula neque.
Aenean et fringilla nulla. In et venenatis massa, vel feugiat diam. Sed ornare felis nec egestas suscipit. Sed a ultricies sapien. Aliquam ex leo, tincidunt faucibus neque non, vehicula commodo velit. Vestibulum molestie efficitur velit in vestibulum. Aliquam eget leo felis. Etiam pharetra vulputate egestas. Cras gravida nibh eu sollicitudin facilisis. Nulla facilisi. Nulla tristique arcu vitae arcu pulvinar feugiat. Suspendisse finibus a urna a cursus. Donec bibendum sodales nunc eget tincidunt. Pellentesque blandit ac nunc at consectetur.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce congue nibh nisl, et porttitor mauris tempor eget. Vivamus sit amet sagittis ligula. Quisque aliquam orci non odio egestas, vel semper felis efficitur. Vivamus non leo lacus. Etiam non ligula eget erat porta laoreet id id ligula. Proin imperdiet erat id efficitur vehicula. Suspendisse potenti. Morbi ornare finibus metus, eu pretium leo tristique sit amet. Praesent placerat elit quis porttitor rhoncus. Vestibulum consectetur turpis sed lacus placerat, vel laoreet est interdum. Proin id quam ut risus tempor hendrerit nec eu lacus. Duis vel aliquam ex.
Sed facilisis in ex vitae pellentesque. Donec tempor lobortis dui. Praesent sagittis, elit ac dictum hendrerit, eros risus auctor erat, in pretium nulla mi et felis. Nullam imperdiet erat id erat rutrum fermentum. Praesent ultrices, diam non efficitur gravida, sem quam fermentum est, vitae tristique libero velit eget turpis. Nunc sem risus, venenatis nec suscipit quis, accumsan eu nunc. Fusce fringilla sit amet purus vel ornare. Donec nulla dolor, gravida ac metus nec, tincidunt feugiat sem. Fusce semper varius nunc.
Nulla facilisi. Quisque in euismod ex, ac sollicitudin dolor. Aliquam erat volutpat. Etiam nisl sem, posuere et pellentesque fermentum, pretium non lorem. Nunc blandit nisl at leo interdum gravida. Proin ullamcorper ultrices dictum. Pellentesque non ligula magna. Sed justo nibh, finibus vitae malesuada ultricies, molestie ac ante. Suspendisse maximus congue viverra.
Donec a est eu arcu tristique fermentum a quis velit. Aenean eu mollis turpis. Morbi euismod risus eros, at vestibulum lectus iaculis sed. Pellentesque varius eu justo in viverra. Phasellus feugiat tincidunt urna ut accumsan. In ullamcorper vehicula hendrerit. Sed sapien diam, rhoncus nec porta non, gravida et ante. Nulla et volutpat quam, nec venenatis ex. Donec vitae dictum libero, id ornare sapien. Morbi id aliquam ipsum. Cras a ultricies purus.
Morbi sit amet sagittis metus, vitae dictum nunc. Pellentesque ornare consequat diam, vitae maximus dolor facilisis at. Cras semper imperdiet mollis. Fusce maximus augue quis elit pulvinar, vitae varius nunc tempus. Maecenas et suscipit leo. Morbi tempus neque enim, sit amet vestibulum ex sollicitudin ac. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel rutrum nisl. Nullam ac vehicula velit. Sed suscipit lacus libero, ac laoreet tortor vehicula a. In aliquam tellus tincidunt ligula fringilla, ut finibus lorem commodo. Sed sit amet porta magna, et aliquam lacus.
Nulla at libero in velit lacinia feugiat sed sit amet erat. Cras nec iaculis magna. Curabitur efficitur turpis vel risus euismod, sit amet posuere orci efficitur. Nunc tincidunt ante eu nunc lacinia, varius dignissim tellus eleifend. Pellentesque enim urna, porttitor eget tincidunt ut, sollicitudin in enim. Donec sit amet hendrerit orci, ut viverra arcu. Nam vitae semper est. Vestibulum aliquet dolor sed turpis blandit eleifend. Nullam auctor accumsan mauris eu mattis. Etiam interdum purus sit amet libero placerat vehicula.
Ut ac odio risus. Sed ut dolor ut metus tincidunt egestas. Curabitur ullamcorper lectus interdum nisi euismod, et faucibus dui fringilla. Nunc at purus vel erat hendrerit dapibus a ut ligula. Nulla facilisi. Etiam gravida, dui nec posuere gravida, nunc quam sodales dui, ut congue mauris tortor vitae nunc. Praesent dapibus mi quis pulvinar consequat. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque ultricies placerat dolor tempus cursus. Etiam vehicula, dui vel varius ullamcorper, sapien sem malesuada felis, quis suscipit est nibh vel massa.
Nulla sed mollis enim. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque magna purus, faucibus vel ornare vel, semper et odio. Donec non interdum nunc. Maecenas metus augue, maximus ac volutpat id, euismod eget sem. Sed efficitur non diam sed ultrices. Fusce ultrices nisl et suscipit tristique. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi luctus augue vel vehicula iaculis.
Vivamus iaculis luctus nisl, quis molestie purus mollis vitae. Proin vehicula rutrum finibus. Nulla lacinia auctor tincidunt. Vivamus sollicitudin orci eu porttitor vehicula. Vivamus auctor sem sed risus porta cursus. Donec orci dui, lacinia vitae mi quis, tincidunt feugiat elit. Mauris pharetra faucibus justo non volutpat. Praesent pellentesque condimentum quam quis porta. Praesent sed nisi id eros iaculis condimentum nec in libero. Donec eu blandit enim. Aliquam nec elementum libero. Donec nec nisi suscipit felis blandit rutrum. Morbi magna nulla, porttitor id nisl vitae, imperdiet efficitur leo. Ut eu vestibulum justo, vitae dapibus felis.
Quisque ac est nec metus sagittis lobortis mollis id metus. Duis a augue eu erat vulputate facilisis varius ac nunc. Suspendisse eleifend enim suscipit erat aliquet, sed feugiat ligula tempor. Aenean dapibus felis porttitor mauris ultricies vehicula. Vestibulum lacinia scelerisque turpis, ut varius nunc suscipit vitae. Praesent blandit mauris eu semper lacinia. Cras mauris augue, tincidunt quis risus tincidunt, blandit euismod erat. Etiam non sagittis leo, eget pharetra risus.
Donec sodales ultricies neque, non accumsan velit blandit non. Aliquam lacinia orci mauris, commodo porttitor ipsum venenatis sed. Integer sit amet pretium nisi. Ut porttitor, sapien quis gravida egestas, nulla tellus ullamcorper ante, et eleifend diam turpis et odio. Quisque dui orci, commodo sit amet rhoncus ut, pharetra ac leo. Suspendisse non vehicula ex. Morbi gravida lacus vitae ex lacinia, nec aliquam purus consequat. Donec aliquam pretium massa, id viverra nunc blandit sit amet. Donec sed dapibus elit. Cras hendrerit efficitur eros quis malesuada. Aenean a massa in dolor gravida volutpat a et nisi. Nullam sit amet est tempus, condimentum odio egestas, dignissim nibh. Integer tempor id sapien at sagittis.
Aliquam in urna semper, suscipit metus in, pharetra lectus. Proin tempor nibh turpis, a pulvinar justo mollis sit amet. Fusce massa turpis, tristique id semper sit amet, venenatis in mauris. Maecenas id consectetur purus, sed efficitur ipsum. Sed pretium nisi ut sem pulvinar ullamcorper. Nullam at nunc et quam rhoncus egestas eu eu odio. Nullam commodo urna cursus massa porta consectetur. Sed blandit erat ut imperdiet malesuada. Cras nec fringilla ante. Nam sed gravida urna. Nam non dui quis turpis efficitur feugiat. Fusce in quam ex.
Nullam purus libero, egestas eget luctus et, malesuada eget est. Curabitur tristique sollicitudin est, imperdiet cras amet. `), []byte(`password`))
Encrypt([]byte("hello, world"), bob)
}
}
func BenchmarkDecrypt(b *testing.B) {
key, _, _ := New([]byte("password"), nil)
msg := []byte("hello, world")
enc, _ := Encrypt(msg, key)
b.ResetTimer()
for i := 0; i < b.N; i++ {
Decrypt(enc, key)
}
}
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++ {
EncryptChaCha([]byte("hello, world"), bob)
}
}
func BenchmarkDecryptChaCha(b *testing.B) {
key, _, _ := NewArgon2([]byte("password"), nil)
msg := []byte("hello, world")
enc, _ := EncryptChaCha(msg, key)
b.ResetTimer()
for i := 0; i < b.N; i++ {
DecryptChaCha(enc, key)
}
}
func TestEncryption(t *testing.T) {
key, salt, err := New([]byte("password"), nil)
assert.Nil(t, err)
msg := []byte("hello, world")
enc, err := Encrypt(msg, key)
assert.Nil(t, err)
dec, err := Decrypt(enc, key)
assert.Nil(t, err)
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, _ := New([]byte("password"), salt)
dec, err = Decrypt(enc, key2)
assert.Nil(t, err)
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, _ = New([]byte("wrong password"), salt)
dec, err = Decrypt(enc, key2)
assert.NotNil(t, err)
assert.NotEqual(t, msg, dec)
// error with no password
_, err = Decrypt([]byte(""), key)
assert.NotNil(t, err)
// error with small password
_, _, err = New([]byte(""), nil)
assert.NotNil(t, err)
}
func TestEncryptionChaCha(t *testing.T) {
key, salt, err := NewArgon2([]byte("password"), nil)
fmt.Printf("key: %x\n", key)
assert.Nil(t, err)
msg := []byte("hello, world")
enc, err := EncryptChaCha(msg, key)
assert.Nil(t, err)
dec, err := DecryptChaCha(enc, key)
assert.Nil(t, err)
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, _ := NewArgon2([]byte("password"), salt)
dec, err = DecryptChaCha(enc, key2)
assert.Nil(t, err)
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, _ = NewArgon2([]byte("wrong password"), salt)
dec, err = DecryptChaCha(enc, key2)
assert.NotNil(t, err)
assert.NotEqual(t, msg, dec)
// error with no password
_, err = DecryptChaCha([]byte(""), key)
assert.NotNil(t, err)
// error with small password
_, _, err = NewArgon2([]byte(""), nil)
assert.NotNil(t, err)
}

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())
}

19
src/install/Makefile Normal file
View File

@ -0,0 +1,19 @@
# VERSION=8.X.Y make release
release:
cd ../../ && go run src/install/updateversion.go
git commit -am "bump ${VERSION}"
git tag -af v${VERSION} -m "v${VERSION}"
git push
git push --tags
cp zsh_autocomplete ../../
cp bash_autocomplete ../../
cd ../../ && goreleaser release
cd ../../ && ./src/install/prepare-sources-tarball.sh
cd ../../ && ./src/install/upload-src-tarball.sh
test:
cp zsh_autocomplete ../../
cp bash_autocomplete ../../
cd ../../ && go generate
cd ../../ && goreleaser release --skip-publish

View File

@ -0,0 +1,19 @@
: ${PROG:=$(basename ${BASH_SOURCE})}
_cli_bash_autocomplete() {
if [[ "${COMP_WORDS[0]}" != "source" ]]; then
local cur opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
if [[ "$cur" == "-"* ]]; then
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} ${cur} --generate-bash-completion )
else
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}
complete -o bashdefault -o default -o nospace -F _cli_bash_autocomplete $PROG
unset PROG

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

767
src/install/default.txt Normal file
View File

@ -0,0 +1,767 @@
#!/bin/bash -
#===============================================================================
#
# FILE: default.txt
#
# USAGE: curl https://getcroc.schollz.com | bash
# OR
# wget -qO- https://getcroc.schollz.com | bash
#
# DESCRIPTION: croc Installer Script.
#
# This script installs croc into a specified prefix.
# Default prefix = /usr/local/bin
#
# OPTIONS: -p, --prefix "${INSTALL_PREFIX}"
# Prefix to install croc into. Defaults to /usr/local/bin
# REQUIREMENTS: bash, uname, tar/unzip, curl/wget, sudo (if not run
# as root), install, mktemp, sha256sum/shasum/sha256
#
# BUGS: ...hopefully not. Please report.
#
# NOTES: Homepage: https://schollz.com/software/croc
# Issues: https://github.com/schollz/croc/issues
#
# CREATED: 08/10/2019 16:41
# REVISION: 0.9.2
#===============================================================================
set -o nounset # Treat unset variables as an error
#-------------------------------------------------------------------------------
# DEFAULTS
#-------------------------------------------------------------------------------
PREFIX="${PREFIX:-}"
ANDROID_ROOT="${ANDROID_ROOT:-}"
# Termux on Android has ${PREFIX} set which already ends with '/usr'
if [[ -n "${ANDROID_ROOT}" && -n "${PREFIX}" ]]; then
INSTALL_PREFIX="${PREFIX}/bin"
else
INSTALL_PREFIX="/usr/local/bin"
fi
#-------------------------------------------------------------------------------
# FUNCTIONS
#-------------------------------------------------------------------------------
#--- FUNCTION ----------------------------------------------------------------
# NAME: print_banner
# DESCRIPTION: Prints a banner
# PARAMETERS: none
# RETURNS: 0
#-------------------------------------------------------------------------------
print_banner() {
cat <<-'EOF'
=================================================
____
/ ___|_ __ ___ ___
| | | '__/ _ \ / __|
| |___| | | (_) | (__
\____|_| \___/ \___|
___ _ _ _
|_ _|_ __ ___| |_ __ _| | | ___ _ __
| || '_ \/ __| __/ _` | | |/ _ \ '__|
| || | | \__ \ || (_| | | | __/ |
|___|_| |_|___/\__\__,_|_|_|\___|_|
==================================================
EOF
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: print_help
# DESCRIPTION: Prints out a help message
# PARAMETERS: none
# RETURNS: 0
#-------------------------------------------------------------------------------
print_help() {
local help_header
local help_message
help_header="croc Installer Script"
help_message="Usage:
-p INSTALL_PREFIX
Prefix to install croc into. Directory must already exist.
Default = /usr/local/bin ('\${PREFIX}/bin' on Termux for Android)
-h
Prints this helpful message and exit."
echo "${help_header}"
echo ""
echo "${help_message}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: print_message
# DESCRIPTION: Prints a message all fancy like
# PARAMETERS: $1 = Message to print
# $2 = Severity. info, ok, error, warn
# RETURNS: Formatted Message to stdout
#-------------------------------------------------------------------------------
print_message() {
local message
local severity
local red
local green
local yellow
local nc
message="${1}"
severity="${2}"
red='\e[0;31m'
green='\e[0;32m'
yellow='\e[1;33m'
nc='\e[0m'
case "${severity}" in
"info" ) echo -e "${nc}${message}${nc}";;
"ok" ) echo -e "${green}${message}${nc}";;
"error" ) echo -e "${red}${message}${nc}";;
"warn" ) echo -e "${yellow}${message}${nc}";;
esac
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: make_tempdir
# DESCRIPTION: Makes a temp dir using mktemp if available
# PARAMETERS: $1 = Directory template
# RETURNS: 0 = Created temp dir. Also prints temp file path to stdout
# 1 = Failed to create temp dir
# 20 = Failed to find mktemp
#-------------------------------------------------------------------------------
make_tempdir() {
local template
local tempdir
local tempdir_rcode
template="${1}.XXXXXX"
if command -v mktemp >/dev/null 2>&1; then
tempdir="$(mktemp -d -t "${template}")"
tempdir_rcode="${?}"
if [[ "${tempdir_rcode}" == "0" ]]; then
echo "${tempdir}"
return 0
else
return 1
fi
else
return 20
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: determine_os
# DESCRIPTION: Attempts to determine host os using uname
# PARAMETERS: none
# RETURNS: 0 = OS Detected. Also prints detected os to stdout
# 1 = Unknown OS
# 20 = 'uname' not found in path
#-------------------------------------------------------------------------------
determine_os() {
local uname_out
if command -v uname >/dev/null 2>&1; then
uname_out="$(uname)"
if [[ "${uname_out}" == "" ]]; then
return 1
else
echo "${uname_out}"
return 0
fi
else
return 20
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: determine_arch
# DESCRIPTION: Attempt to determine architecture of host
# PARAMETERS: none
# RETURNS: 0 = Arch Detected. Also prints detected arch to stdout
# 1 = Unknown arch
# 20 = 'uname' not found in path
#-------------------------------------------------------------------------------
determine_arch() {
local uname_out
if command -v uname >/dev/null 2>&1; then
uname_out="$(uname -m)"
if [[ "${uname_out}" == "" ]]; then
return 1
else
echo "${uname_out}"
return 0
fi
else
return 20
fi
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: download_file
# DESCRIPTION: Downloads a file into the specified directory. Attempts to
# use curl, then wget. If neither is found, fail.
# PARAMETERS: $1 = url of file to download
# $2 = location to download file into on host system
# RETURNS: If curl or wget found, returns the return code of curl or wget
# 20 = Could not find curl and wget
#-------------------------------------------------------------------------------
download_file() {
local url
local dir
local filename
local rcode
url="${1}"
dir="${2}"
filename="${3}"
if command -v curl >/dev/null 2>&1; then
curl -fsSL "${url}" -o "${dir}/${filename}"
rcode="${?}"
elif command -v wget >/dev/null 2>&1; then
wget --quiet "${url}" -O "${dir}/${filename}"
rcode="${?}"
else
rcode="20"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: checksum_check
# DESCRIPTION: Attempt to verify checksum of downloaded file to ensure
# integrity. Tries multiple tools before failing.
# PARAMETERS: $1 = path to checksum file
# $2 = location of file to check
# $3 = working directory
# RETURNS: 0 = checkusm verified
# 1 = checksum verification failed
# 20 = failed to determine tool to use to check checksum
# 30 = failed to change into or go back from working dir
#-------------------------------------------------------------------------------
checksum_check() {
local checksum_file
local file
local dir
local rcode
local shasum_1
local shasum_2
local shasum_c
checksum_file="${1}"
file="${2}"
dir="${3}"
cd "${dir}" || return 30
if command -v sha256sum >/dev/null 2>&1; then
## Not all sha256sum versions seem to have --ignore-missing, so filter the checksum file
## to only include the file we downloaded.
grep "$(basename "${file}")" "${checksum_file}" > filtered_checksum.txt
shasum_c="$(sha256sum -c "filtered_checksum.txt")"
rcode="${?}"
elif command -v shasum >/dev/null 2>&1; then
## With shasum on FreeBSD, we don't get to --ignore-missing, so filter the checksum file
## to only include the file we downloaded.
grep "$(basename "${file}")" "${checksum_file}" > filtered_checksum.txt
shasum_c="$(shasum -a 256 -c "filtered_checksum.txt")"
rcode="${?}"
elif command -v sha256 >/dev/null 2>&1; then
## With sha256 on FreeBSD, we don't get to --ignore-missing, so filter the checksum file
## to only include the file we downloaded.
## Also sha256 -c option seems to fail, so fall back to an if statement
grep "$(basename "${file}")" "${checksum_file}" > filtered_checksum.txt
shasum_1="$(sha256 -q "${file}")"
shasum_2="$(awk '{print $1}' filtered_checksum.txt)"
if [[ "${shasum_1}" == "${shasum_2}" ]]; then
rcode="0"
else
rcode="1"
fi
shasum_c="Expected: ${shasum_1}, Got: ${shasum_2}"
else
return 20
fi
cd - >/dev/null 2>&1 || return 30
if [[ "${rcode}" -gt "0" ]]; then
echo "${shasum_c}"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: extract_file
# DESCRIPTION: Extracts a file into a location. Attempts to determine which
# tool to use by checking file extension.
# PARAMETERS: $1 = file to extract
# $2 = location to extract file into
# $3 = extension
# RETURNS: Return code of the tool used to extract the file
# 20 = Failed to determine which tool to use
# 30 = Failed to find tool in path
#-------------------------------------------------------------------------------
extract_file() {
local file
local dir
local ext
local rcode
file="${1}"
dir="${2}"
ext="${3}"
case "${ext}" in
"zip" ) if command -v unzip >/dev/null 2>&1; then
unzip "${file}" -d "${dir}"
rcode="${?}"
else
rcode="30"
fi
;;
"tar.gz" ) if command -v tar >/dev/null 2>&1; then
tar -xf "${file}" -C "${dir}"
rcode="${?}"
else
rcode="31"
fi
;;
* ) rcode="20";;
esac
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: create_prefix
# DESCRIPTION: Creates the install prefix (and any parent directories). If
# EUID not 0, then attempt to use sudo.
# PARAMETERS: $1 = prefix
# RETURNS: Return code of the tool used to make the directory
# 0 = Created the directory
# >0 = Failed to create directory
# 20 = Could not find mkdir command
# 21 = Could not find sudo command
#-------------------------------------------------------------------------------
create_prefix() {
local prefix
local rcode
prefix="${1}"
if command -v mkdir >/dev/null 2>&1; then
if [[ "${EUID}" == "0" ]]; then
mkdir -p "${prefix}"
rcode="${?}"
else
if command -v sudo >/dev/null 2>&1; then
sudo mkdir -p "${prefix}"
rcode="${?}"
else
rcode="21"
fi
fi
else
rcode="20"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: install_file_freebsd
# DESCRIPTION: Installs a file into a location using 'install'. If EUID not
# 0, then attempt to use sudo.
# PARAMETERS: $1 = file to install
# $2 = location to install file into
# RETURNS: 0 = File Installed
# 1 = File not installed
# 20 = Could not find install command
# 21 = Could not find sudo command
#-------------------------------------------------------------------------------
install_file_freebsd() {
local file
local prefix
local rcode
file="${1}"
prefix="${2}"
if command -v install >/dev/null 2>&1; then
if [[ "${EUID}" == "0" ]]; then
install -C -b -B '_old' -m 755 "${file}" "${prefix}"
rcode="${?}"
else
if command -v sudo >/dev/null 2>&1; then
sudo install -C -b -B '_old' -m 755 "${file}" "${prefix}"
rcode="${?}"
else
rcode="21"
fi
fi
else
rcode="20"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: install_file_linux
# DESCRIPTION: Installs a file into a location using 'install'. If EUID not
# 0, then attempt to use sudo (unless on android).
# PARAMETERS: $1 = file to install
# $2 = location to install file into
# RETURNS: 0 = File Installed
# 1 = File not installed
# 20 = Could not find install command
# 21 = Could not find sudo command
#-------------------------------------------------------------------------------
install_file_linux() {
local file
local prefix
local rcode
file="${1}"
prefix="${2}"
if command -v install >/dev/null 2>&1; then
if [[ "${EUID}" == "0" ]]; then
install -C -b -S '_old' -m 755 -t "${prefix}" "${file}"
rcode="${?}"
else
if command -v sudo >/dev/null 2>&1; then
sudo install -C -b -S '_old' -m 755 "${file}" "${prefix}"
rcode="${?}"
elif [[ "${ANDROID_ROOT}" != "" ]]; then
install -C -b -S '_old' -m 755 -t "${prefix}" "${file}"
rcode="${?}"
else
rcode="21"
fi
fi
else
rcode="20"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: install_file_cygwin
# DESCRIPTION: Installs a file into a location using 'install'. If EUID not
# 0, then attempt to use sudo.
# Not really 100% sure this is how to install croc in cygwin.
# PARAMETERS: $1 = file to install
# $2 = location to install file into
# RETURNS: 0 = File Installed
# 20 = Could not find install command
# 21 = Could not find sudo command
#-------------------------------------------------------------------------------
install_file_cygwin() {
local file
local prefix
local rcode
file="${1}"
prefix="${2}"
if command -v install >/dev/null 2>&1; then
if [[ "${EUID}" == "0" ]]; then
install -m 755 "${prefix}" "${file}"
rcode="${?}"
else
if command -v sudo >/dev/null 2>&1; then
sudo install -m 755 "${file}" "${prefix}"
rcode="${?}"
else
rcode="21"
fi
fi
else
rcode="20"
fi
return "${rcode}"
}
#--- FUNCTION ----------------------------------------------------------------
# NAME: main
# DESCRIPTION: Put it all together in a logical way
# ...at least that is the hope...
# PARAMETERS: 1 = prefix
# RETURNS: 0 = All good
# 1 = Something done broke
#-------------------------------------------------------------------------------
main() {
local prefix
local tmpdir
local tmpdir_rcode
local croc_arch
local croc_arch_rcode
local croc_os
local croc_os_rcode
local croc_base_url
local croc_url
local croc_file
local croc_checksum_file
local croc_bin_name
local croc_version
local croc_dl_ext
local download_file_rcode
local download_checksum_file_rcode
local checksum_check_rcode
local extract_file_rcode
local install_file_rcode
local create_prefix_rcode
local bash_autocomplete_file
local bash_autocomplete_prefix
local zsh_autocomplete_file
local zsh_autocomplete_prefix
local autocomplete_install_rcode
croc_bin_name="croc"
croc_version="10.1.1"
croc_dl_ext="tar.gz"
croc_base_url="https://github.com/schollz/croc/releases/download"
prefix="${1}"
bash_autocomplete_file="bash_autocomplete"
bash_autocomplete_prefix="/etc/bash_completion.d"
zsh_autocomplete_file="zsh_autocomplete"
zsh_autocomplete_prefix="/etc/zsh"
print_banner
print_message "== Install prefix set to ${prefix}" "info"
tmpdir="$(make_tempdir "${croc_bin_name}")"
tmpdir_rcode="${?}"
if [[ "${tmpdir_rcode}" == "0" ]]; then
print_message "== Created temp dir at ${tmpdir}" "info"
elif [[ "${tmpdir_rcode}" == "1" ]]; then
print_message "== Failed to create temp dir at ${tmpdir}" "error"
else
print_message "== 'mktemp' not found in path. Is it installed?" "error"
exit 1
fi
croc_arch="$(determine_arch)"
croc_arch_rcode="${?}"
if [[ "${croc_arch_rcode}" == "0" ]]; then
print_message "== Architecture detected as ${croc_arch}" "info"
elif [[ "${croc_arch_rcode}" == "1" ]]; then
print_message "== Architecture not detected" "error"
exit 1
else
print_message "== 'uname' not found in path. Is it installed?" "error"
exit 1
fi
croc_os="$(determine_os)"
croc_os_rcode="${?}"
if [[ "${croc_os_rcode}" == "0" ]]; then
print_message "== OS detected as ${croc_os}" "info"
elif [[ "${croc_os_rcode}" == "1" ]]; then
print_message "== OS not detected" "error"
exit 1
else
print_message "== 'uname' not found in path. Is it installed?" "error"
exit 1
fi
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";
exit 1;;
esac
case "${croc_arch}" in
"x86_64" ) croc_arch="64bit";;
"amd64" ) croc_arch="64bit";;
"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
croc_file="${croc_bin_name}_v${croc_version}_${croc_os}-${croc_arch}.${croc_dl_ext}"
croc_checksum_file="${croc_bin_name}_v${croc_version}_checksums.txt"
croc_url="${croc_base_url}/v${croc_version}/${croc_file}"
croc_checksum_url="${croc_base_url}/v${croc_version}/${croc_checksum_file}"
echo "${croc_url}" "${tmpdir}" "${croc_file}"
download_file "${croc_url}" "${tmpdir}" "${croc_file}"
download_file_rcode="${?}"
if [[ "${download_file_rcode}" == "0" ]]; then
print_message "== Downloaded croc archive into ${tmpdir}" "info"
elif [[ "${download_file_rcode}" == "1" ]]; then
print_message "== Failed to download croc archive" "error"
exit 1
elif [[ "${download_file_rcode}" == "20" ]]; then
print_message "== Failed to locate curl or wget" "error"
exit 1
else
print_message "== Return code of download tool returned an unexpected value of ${download_file_rcode}" "error"
exit 1
fi
download_file "${croc_checksum_url}" "${tmpdir}" "${croc_checksum_file}"
download_checksum_file_rcode="${?}"
if [[ "${download_checksum_file_rcode}" == "0" ]]; then
print_message "== Downloaded croc checksums file into ${tmpdir}" "info"
elif [[ "${download_checksum_file_rcode}" == "1" ]]; then
print_message "== Failed to download croc checksums" "error"
exit 1
elif [[ "${download_checksum_file_rcode}" == "20" ]]; then
print_message "== Failed to locate curl or wget" "error"
exit 1
else
print_message "== Return code of download tool returned an unexpected value of ${download_checksum_file_rcode}" "error"
exit 1
fi
checksum_check "${tmpdir}/${croc_checksum_file}" "${tmpdir}/${croc_file}" "${tmpdir}"
checksum_check_rcode="${?}"
if [[ "${checksum_check_rcode}" == "0" ]]; then
print_message "== Checksum of ${tmpdir}/${croc_file} verified" "ok"
elif [[ "${checksum_check_rcode}" == "1" ]]; then
print_message "== Failed to verify checksum of ${tmpdir}/${croc_file}" "error"
exit 1
elif [[ "${checksum_check_rcode}" == "20" ]]; then
print_message "== Failed to find tool to verify sha256 sums" "error"
exit 1
elif [[ "${checksum_check_rcode}" == "30" ]]; then
print_message "== Failed to change into working directory ${tmpdir}" "error"
exit 1
else
print_message "== Unknown return code returned while checking checksum of ${tmpdir}/${croc_file}. Returned ${checksum_check_rcode}" "error"
exit 1
fi
extract_file "${tmpdir}/${croc_file}" "${tmpdir}/" "${croc_dl_ext}"
extract_file_rcode="${?}"
if [[ "${extract_file_rcode}" == "0" ]]; then
print_message "== Extracted ${croc_file} to ${tmpdir}/" "info"
elif [[ "${extract_file_rcode}" == "1" ]]; then
print_message "== Failed to extract ${croc_file}" "error"
exit 1
elif [[ "${extract_file_rcode}" == "20" ]]; then
print_message "== Failed to determine which extraction tool to use" "error"
exit 1
elif [[ "${extract_file_rcode}" == "30" ]]; then
print_message "== Failed to find 'unzip' in path" "error"
exit 1
elif [[ "${extract_file_rcode}" == "31" ]]; then
print_message "== Failed to find 'tar' in path" "error"
exit 1
else
print_message "== Unknown error returned from extraction attempt" "error"
exit 1
fi
if [[ ! -d "${prefix}" ]]; then
create_prefix "${prefix}"
create_prefix_rcode="${?}"
if [[ "${create_prefix_rcode}" == "0" ]]; then
print_message "== Created install prefix at ${prefix}" "info"
elif [[ "${create_prefix_rcode}" == "20" ]]; then
print_message "== Failed to find mkdir in path" "error"
exit 1
elif [[ "${create_prefix_rcode}" == "21" ]]; then
print_message "== Failed to find sudo in path" "error"
exit 1
else
print_message "== Failed to create the install prefix: ${prefix}" "error"
exit 1
fi
else
print_message "== Install prefix already exists. No need to create it." "info"
fi
[ ! -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="${?}";;
"FreeBSD" ) install_file_freebsd "${tmpdir}/${croc_bin_name}" "${prefix}/";
install_file_rcode="${?}";;
"macOS" ) install_file_freebsd "${tmpdir}/${croc_bin_name}" "${prefix}/";
install_file_rcode="${?}";;
"Windows" ) install_file_cygwin "${tmpdir}/${croc_bin_name}" "${prefix}/";
install_file_rcode="${?}";;
esac
if [[ "${install_file_rcode}" == "0" ]] ; then
print_message "== Installed ${croc_bin_name} to ${prefix}/" "ok"
elif [[ "${install_file_rcode}" == "1" ]]; then
print_message "== Failed to install ${croc_bin_name}" "error"
exit 1
elif [[ "${install_file_rcode}" == "20" ]]; then
print_message "== Failed to locate 'install' command" "error"
exit 1
elif [[ "${install_file_rcode}" == "21" ]]; then
print_message "== Failed to locate 'sudo' command" "error"
exit 1
else
print_message "== Install attempt returned an unexpected value of ${install_file_rcode}" "error"
exit 1
fi
# case "$(basename ${SHELL})" in
# "bash" ) install_file_linux "${tmpdir}/${bash_autocomplete_file}" "${bash_autocomplete_prefix}/croc";
# autocomplete_install_rcode="${?}";;
# "zsh" ) install_file_linux "${tmpdir}/${zsh_autocomplete_file}" "${zsh_autocomplete_prefix}/zsh_autocomplete_croc";
# autocomplete_install_rcode="${?}";
# print_message "== You will need to add the following to your ~/.zshrc to enable autocompletion" "info";
# print_message "\nPROG=croc\n_CLI_ZSH_AUTOCOMPLETE_HACK=1\nsource /etc/zsh/zsh_autocomplete_croc\n" "info";;
# *) autocomplete_install_rcode="1";;
# esac
# if [[ "${autocomplete_install_rcode}" == "0" ]] ; then
# print_message "== Installed autocompletions for $(basename "${SHELL}")" "ok"
# elif [[ "${autocomplete_install_rcode}" == "1" ]]; then
# print_message "== Failed to install ${bash_autocomplete_file}" "error"
# elif [[ "${autocomplete_install_rcode}" == "20" ]]; then
# print_message "== Failed to locate 'install' command" "error"
# elif [[ "${autocomplete_install_rcode}" == "21" ]]; then
# print_message "== Failed to locate 'sudo' command" "error"
# else
# print_message "== Install attempt returned an unexpected value of ${autocomplete_install_rcode}" "error"
# fi
print_message "== Installation complete" "ok"
exit 0
}
#-------------------------------------------------------------------------------
# ARGUMENT PARSING
#-------------------------------------------------------------------------------
OPTS="hp:"
while getopts "${OPTS}" optchar; do
case "${optchar}" in
'h' ) print_help
exit 0
;;
'p' ) INSTALL_PREFIX="${OPTARG}"
;;
/? ) print_message "Unknown option ${OPTARG}" "warn"
;;
esac
done
#-------------------------------------------------------------------------------
# CALL MAIN
#-------------------------------------------------------------------------------
main "${INSTALL_PREFIX}"

View File

@ -0,0 +1,7 @@
#!/bin/bash
tmp=$(mktemp -d)
echo $VERSION
git clone -b v${VERSION} --depth 1 https://github.com/schollz/croc $tmp/croc-${VERSION}
(cd $tmp/croc-${VERSION} && go mod tidy && go mod vendor)
(cd $tmp && tar -cvzf croc_${VERSION}_src.tar.gz croc-${VERSION})
mv $tmp/croc_${VERSION}_src.tar.gz dist/

View File

@ -0,0 +1,77 @@
package main
import (
"fmt"
"os"
"os/exec"
"strings"
)
func main() {
err := run()
if err != nil {
fmt.Println(err)
}
}
func run() (err error) {
versionNew := "v" + os.Getenv("VERSION")
versionHash, err := exec.Command("git", "rev-parse", "--short", "HEAD").Output()
if err != nil {
return
}
versionHashNew := strings.TrimSpace(string(versionHash))
fmt.Println(versionNew)
fmt.Println(versionHashNew)
err = replaceInFile("src/cli/cli.go", `Version = "`, `"`, versionNew+"-"+versionHashNew)
if err == nil {
fmt.Printf("updated cli.go to version %s\n", versionNew)
}
err = replaceInFile("README.md", `version-`, `-b`, strings.Split(versionNew, "-")[0])
if err == nil {
fmt.Printf("updated README to version %s\n", strings.Split(versionNew, "-")[0])
}
err = replaceInFile("src/install/default.txt", `croc_version="`, `"`, strings.Split(versionNew, "-")[0][1:])
if err == nil {
fmt.Printf("updated default.txt to version %s\n", strings.Split(versionNew, "-")[0][1:])
}
return
}
func replaceInFile(fname, start, end, replacement string) (err error) {
b, err := os.ReadFile(fname)
if err != nil {
return
}
oldVersion := GetStringInBetween(string(b), start, end)
if oldVersion == "" {
err = fmt.Errorf("nothing")
return
}
newF := strings.Replace(
string(b),
fmt.Sprintf("%s%s%s", start, oldVersion, end),
fmt.Sprintf("%s%s%s", start, replacement, end),
1,
)
err = os.WriteFile(fname, []byte(newF), 0o644)
return
}
// GetStringInBetween Returns empty string if no start string found
func GetStringInBetween(str string, start string, end string) (result string) {
s := strings.Index(str, start)
if s == -1 {
return
}
s += len(start)
e := strings.Index(str[s:], end)
if e == -1 {
return
}
e += s
return str[s:e]
}

View File

@ -0,0 +1,51 @@
#!/bin/bash
VERSION=$(cat ./src/cli/cli.go | grep 'Version = "v' | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')
echo $VERSION
# Check dependencies.
set -e
xargs=$(which gxargs || which xargs)
# Validate settings.
[ "$TRACE" ] && set -x
CONFIG=$@
for line in $CONFIG; do
eval "$line"
done
owner="schollz"
repo="croc"
tag="v${VERSION}"
filename="dist/croc_${VERSION}_src.tar.gz"
# Define variables.
GH_API="https://api.github.com"
GH_REPO="$GH_API/repos/$owner/$repo"
GH_TAGS="$GH_REPO/releases/tags/$tag"
AUTH="Authorization: token $GITHUB_TOKEN"
WGET_ARGS="--content-disposition --auth-no-challenge --no-cookie"
CURL_ARGS="-LJO#"
if [[ "$tag" == 'LATEST' ]]; then
GH_TAGS="$GH_REPO/releases/latest"
fi
# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!"; exit 1; }
# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)
# Get ID of the asset based on given filename.
eval $(echo "$response" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
[ "$id" ] || { echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2; exit 1; }
# Upload asset
echo "Uploading asset... "
# Construct url
GH_ASSET="https://uploads.github.com/repos/$owner/$repo/releases/$id/assets?name=$(basename $filename)"
curl "$GITHUB_OAUTH_BASIC" --data-binary @"$filename" -H "Authorization: token $GITHUB_TOKEN" -H "Content-Type: application/octet-stream" $GH_ASSET

View File

@ -0,0 +1,23 @@
#compdef $PROG
_cli_zsh_autocomplete() {
local -a opts
local cur
cur=${words[-1]}
if [[ "$cur" == "-"* ]]; then
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} ${cur} --generate-bash-completion)}")
else
opts=("${(@f)$(_CLI_ZSH_AUTOCOMPLETE_HACK=1 ${words[@]:0:#words[@]-1} --generate-bash-completion)}")
fi
if [[ "${opts[1]}" != "" ]]; then
_describe 'values' opts
else
_files
fi
return
}
compdef _cli_zsh_autocomplete $PROG

View File

@ -1,43 +0,0 @@
package logger
import (
log "github.com/cihub/seelog"
)
// SetLogLevel determines the log level
func SetLogLevel(level string) (err error) {
// https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit
// https://github.com/cihub/seelog/wiki/Log-levels
appConfig := `
<seelog minlevel="` + level + `">
<outputs formatid="stdout">
<filter levels="debug,trace">
<console formatid="debug"/>
</filter>
<filter levels="info">
<console formatid="info"/>
</filter>
<filter levels="critical,error">
<console formatid="error"/>
</filter>
<filter levels="warn">
<console formatid="warn"/>
</filter>
</outputs>
<formats>
<format id="stdout" format="%Date %Time [%LEVEL] %File %FuncShort:%Line %Msg %n" />
<format id="debug" format="%Date %Time %EscM(37)[%LEVEL]%EscM(0) %File %FuncShort:%Line %Msg %n" />
<format id="info" format="%Date %Time %EscM(36)[%LEVEL]%EscM(0) %File %FuncShort:%Line %Msg %n" />
<format id="warn" format="%Date %Time %EscM(33)[%LEVEL]%EscM(0) %File %FuncShort:%Line %Msg %n" />
<format id="error" format="%Date %Time %EscM(31)[%LEVEL]%EscM(0) %File %FuncShort:%Line %Msg %n" />
</formats>
</seelog>
`
logger, err := log.LoggerFromConfigAsBytes([]byte(appConfig))
if err != nil {
return
}
log.ReplaceLogger(logger)
return
}

84
src/message/message.go Normal file
View File

@ -0,0 +1,84 @@
package message
import (
"encoding/json"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/compress"
"github.com/schollz/croc/v10/src/crypt"
log "github.com/schollz/logger"
)
// Type is a message type
type Type string
const (
TypePAKE Type = "pake"
TypeExternalIP Type = "externalip"
TypeFinished Type = "finished"
TypeError Type = "error"
TypeCloseRecipient Type = "close-recipient"
TypeCloseSender Type = "close-sender"
TypeRecipientReady Type = "recipientready"
TypeFileInfo Type = "fileinfo"
)
// Message is the possible payload for messaging
type Message struct {
Type Type `json:"t,omitempty"`
Message string `json:"m,omitempty"`
Bytes []byte `json:"b,omitempty"`
Bytes2 []byte `json:"b2,omitempty"`
Num int `json:"n,omitempty"`
}
func (m Message) String() string {
b, _ := json.Marshal(m)
return string(b)
}
// Send will send out
func Send(c *comm.Comm, key []byte, m Message) (err error) {
mSend, err := Encode(key, m)
if err != nil {
return
}
err = c.Send(mSend)
return
}
// Encode will convert to bytes
func Encode(key []byte, m Message) (b []byte, err error) {
b, err = json.Marshal(m)
if err != nil {
return
}
b = compress.Compress(b)
if key != nil {
log.Debugf("writing %s message (encrypted)", m.Type)
b, err = crypt.Encrypt(b, key)
} else {
log.Debugf("writing %s message (unencrypted)", m.Type)
}
return
}
// Decode will convert from bytes
func Decode(key []byte, b []byte) (m Message, err error) {
if key != nil {
b, err = crypt.Decrypt(b, key)
if err != nil {
return
}
}
b = compress.Decompress(b)
err = json.Unmarshal(b, &m)
if err == nil {
if key != nil {
log.Debugf("read %s message (encrypted)", m.Type)
} else {
log.Debugf("read %s message (unencrypted)", m.Type)
}
}
return
}

View File

@ -0,0 +1,96 @@
package message
import (
"crypto/rand"
"fmt"
"net"
"testing"
"time"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/crypt"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
var TypeMessage Type = "message"
func TestMessage(t *testing.T) {
log.SetLevel("debug")
m := Message{Type: TypeMessage, Message: "hello, world"}
e, salt, err := crypt.New([]byte("pass"), nil)
assert.Nil(t, err)
fmt.Println(string(salt))
b, err := Encode(e, m)
assert.Nil(t, err)
fmt.Printf("%x\n", b)
m2, err := Decode(e, b)
assert.Nil(t, err)
assert.Equal(t, m, m2)
assert.Equal(t, `{"t":"message","m":"hello, world"}`, m.String())
_, err = Decode([]byte("not pass"), b)
assert.NotNil(t, err)
_, err = Encode([]byte("0"), m)
assert.NotNil(t, err)
}
func TestMessageNoPass(t *testing.T) {
log.SetLevel("debug")
m := Message{Type: TypeMessage, Message: "hello, world"}
b, err := Encode(nil, m)
assert.Nil(t, err)
fmt.Printf("%x\n", b)
m2, err := Decode(nil, b)
assert.Nil(t, err)
assert.Equal(t, m, m2)
assert.Equal(t, `{"t":"message","m":"hello, world"}`, m.String())
}
func TestSend(t *testing.T) {
token := make([]byte, 40000000)
rand.Read(token)
port := "8801"
go func() {
log.Debugf("starting TCP server on " + port)
server, err := net.Listen("tcp", "0.0.0.0:"+port)
if err != nil {
log.Error(err)
}
defer server.Close()
// spawn a new goroutine whenever a client connects
for {
connection, err := server.Accept()
if err != nil {
log.Error(err)
}
log.Debugf("client %s connected", connection.RemoteAddr().String())
go func(_ string, connection net.Conn) {
c := comm.New(connection)
err = c.Send([]byte("hello, world"))
assert.Nil(t, err)
data, err := c.Receive()
assert.Nil(t, err)
assert.Equal(t, []byte("hello, computer"), data)
data, err = c.Receive()
assert.Nil(t, err)
assert.Equal(t, []byte{'\x00'}, data)
data, err = c.Receive()
assert.Nil(t, err)
assert.Equal(t, token, data)
}(port, connection)
}
}()
time.Sleep(800 * time.Millisecond)
a, err := comm.NewConnection("127.0.0.1:"+port, 10*time.Minute)
assert.Nil(t, err)
m := Message{Type: TypeMessage, Message: "hello, world"}
e, salt, err := crypt.New([]byte("pass"), nil)
log.Debug(salt)
assert.Nil(t, err)
assert.Nil(t, Send(a, e, m))
}

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",
}

View File

@ -1,4 +1,169 @@
package models
const WEBSOCKET_BUFFER_SIZE = 1024 * 1024 * 32
import (
"context"
"fmt"
"net"
"os"
"path"
"time"
"github.com/schollz/croc/v10/src/utils"
log "github.com/schollz/logger"
)
// TCP_BUFFER_SIZE is the maximum packet size
const TCP_BUFFER_SIZE = 1024 * 64
// DEFAULT_RELAY is the default relay used (can be set using --relay)
var (
DEFAULT_RELAY = "croc.schollz.com"
DEFAULT_RELAY6 = "croc6.schollz.com"
DEFAULT_PORT = "9009"
DEFAULT_PASSPHRASE = "pass123"
INTERNAL_DNS = false
)
// publicDNS are servers to be queried if a local lookup fails
var publicDNS = []string{
"1.0.0.1", // Cloudflare
"1.1.1.1", // Cloudflare
"[2606:4700:4700::1111]", // Cloudflare
"[2606:4700:4700::1001]", // Cloudflare
"8.8.4.4", // Google
"8.8.8.8", // Google
"[2001:4860:4860::8844]", // Google
"[2001:4860:4860::8888]", // Google
"9.9.9.9", // Quad9
"149.112.112.112", // Quad9
"[2620:fe::fe]", // Quad9
"[2620:fe::fe:9]", // Quad9
"8.26.56.26", // Comodo
"8.20.247.20", // Comodo
"208.67.220.220", // Cisco OpenDNS
"208.67.222.222", // Cisco OpenDNS
"[2620:119:35::35]", // Cisco OpenDNS
"[2620:119:53::53]", // Cisco OpenDNS
}
func getConfigFile(requireValidPath bool) (fname string, err error) {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
return
}
fname = path.Join(configFile, "internal-dns")
return
}
func init() {
log.SetLevel("info")
log.SetOutput(os.Stderr)
doRemember := false
for _, flag := range os.Args {
if flag == "--internal-dns" {
INTERNAL_DNS = true
break
}
if flag == "--remember" {
doRemember = true
}
}
if doRemember {
// save in config file
fname, err := getConfigFile(true)
if err == nil {
f, _ := os.Create(fname)
f.Close()
}
}
if !INTERNAL_DNS {
fname, err := getConfigFile(false)
if err == nil {
INTERNAL_DNS = utils.Exists(fname)
}
}
log.Trace("Using internal DNS: ", INTERNAL_DNS)
var err error
var addr string
addr, err = lookup(DEFAULT_RELAY)
if err == nil {
DEFAULT_RELAY = net.JoinHostPort(addr, DEFAULT_PORT)
} else {
DEFAULT_RELAY = ""
}
log.Tracef("Default ipv4 relay: %s", addr)
addr, err = lookup(DEFAULT_RELAY6)
if err == nil {
DEFAULT_RELAY6 = net.JoinHostPort(addr, DEFAULT_PORT)
} else {
DEFAULT_RELAY6 = ""
}
log.Tracef("Default ipv6 relay: %s", addr)
}
// Resolve a hostname to an IP address using DNS.
func lookup(address string) (ipaddress string, err error) {
if !INTERNAL_DNS {
log.Tracef("Using local DNS to resolve %s", address)
return localLookupIP(address)
}
type Result struct {
s string
err error
}
result := make(chan Result, len(publicDNS))
for _, dns := range publicDNS {
go func(dns string) {
var r Result
r.s, r.err = remoteLookupIP(address, dns)
log.Tracef("Resolved %s to %s using %s", address, r.s, dns)
result <- r
}(dns)
}
for i := 0; i < len(publicDNS); i++ {
ipaddress = (<-result).s
log.Tracef("Resolved %s to %s", address, ipaddress)
if ipaddress != "" {
return
}
}
err = fmt.Errorf("failed to resolve %s: all DNS servers exhausted", address)
return
}
// localLookupIP returns a host's IP address using the local DNS configuration.
func localLookupIP(address string) (ipaddress string, err error) {
// Create a context with a 500 millisecond timeout
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
r := &net.Resolver{}
// Use the context with timeout in the LookupHost function
ip, err := r.LookupHost(ctx, address)
if err != nil {
return
}
ipaddress = ip[0]
return
}
// remoteLookupIP returns a host's IP address based on a remote DNS server.
func remoteLookupIP(address, dns string) (ipaddress string, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
d := new(net.Dialer)
return d.DialContext(ctx, network, dns+":53")
},
}
ip, err := r.LookupHost(ctx, address)
if err != nil {
return
}
ipaddress = ip[0]
return
}

View File

@ -1,14 +0,0 @@
package models
import "time"
// FileStats are the file stats transfered to the other
type FileStats struct {
Name string
Size int64
ModTime time.Time
IsDir bool
SentName string
IsCompressed bool
IsEncrypted bool
}

View File

@ -1,527 +0,0 @@
package recipient
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
"os"
"strconv"
"strings"
"sync"
"time"
humanize "github.com/dustin/go-humanize"
log "github.com/cihub/seelog"
"github.com/gorilla/websocket"
"github.com/schollz/croc/src/comm"
"github.com/schollz/croc/src/compress"
"github.com/schollz/croc/src/crypt"
"github.com/schollz/croc/src/logger"
"github.com/schollz/croc/src/models"
"github.com/schollz/croc/src/utils"
"github.com/schollz/croc/src/zipper"
"github.com/schollz/pake"
"github.com/schollz/progressbar/v2"
"github.com/schollz/spinner"
"github.com/tscholl2/siec"
)
var DebugLevel string
// Receive is the async operation to receive a file
func Receive(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) {
logger.SetLogLevel(DebugLevel)
err := receive(forceSend, serverAddress, tcpPorts, isLocal, c, codephrase, noPrompt, useStdout)
if err != nil {
if !strings.HasPrefix(err.Error(), "websocket: close 100") {
fmt.Fprintf(os.Stderr, "\n"+err.Error())
}
}
done <- struct{}{}
}
func receive(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, codephrase string, noPrompt bool, useStdout bool) (err error) {
var fstats models.FileStats
var sessionKey []byte
var transferTime time.Duration
var hash256 []byte
var otherIP string
var progressFile string
var resumeFile bool
var tcpConnections []comm.Comm
dataChan := make(chan []byte, 1024*1024)
isConnectedIfUsingTCP := make(chan bool)
blocks := []string{}
useWebsockets := true
switch forceSend {
case 0:
if !isLocal {
useWebsockets = false
}
case 1:
useWebsockets = true
case 2:
useWebsockets = false
}
// start a spinner
spin := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
spin.Writer = os.Stderr
spin.Suffix = " performing PAKE..."
spin.Start()
// pick an elliptic curve
curve := siec.SIEC255()
// both parties should have a weak key
pw := []byte(codephrase)
// initialize recipient Q ("1" indicates recipient)
Q, err := pake.Init(pw, 1, curve, 1*time.Millisecond)
if err != nil {
return
}
step := 0
for {
messageType, message, err := c.ReadMessage()
if err != nil {
return err
}
if messageType == websocket.PongMessage || messageType == websocket.PingMessage {
continue
}
if messageType == websocket.TextMessage && bytes.Equal(message, []byte("interrupt")) {
return errors.New("\rinterrupted by other party")
}
log.Debugf("got %d: %s", messageType, message)
switch step {
case 0:
// sender has initiated, sends their ip address
otherIP = string(message)
log.Debugf("sender IP: %s", otherIP)
// recipient begins by sending address
ip := ""
if isLocal {
ip = utils.LocalIP()
} else {
ip, _ = utils.PublicIP()
}
c.WriteMessage(websocket.BinaryMessage, []byte(ip))
case 1:
// Q receives u
log.Debugf("[%d] Q computes k, sends H(k), v back to P", step)
if err := Q.Update(message); err != nil {
return err
}
// Q has the session key now, but we will still check if its valid
sessionKey, err = Q.SessionKey()
if err != nil {
return err
}
log.Debugf("%x\n", sessionKey)
// initialize TCP connections if using (possible, but unlikely, race condition)
go func() {
if !useWebsockets {
log.Debugf("connecting to server")
tcpConnections = make([]comm.Comm, len(tcpPorts))
for i, tcpPort := range tcpPorts {
log.Debugf("connecting to %d", i)
tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
if err != nil {
log.Error(err)
}
}
log.Debugf("fully connected")
}
isConnectedIfUsingTCP <- true
}()
c.WriteMessage(websocket.BinaryMessage, Q.Bytes())
case 2:
log.Debugf("[%d] Q recieves H(k) from P", step)
// check if everything is still kosher with our computed session key
if err := Q.Update(message); err != nil {
return err
}
c.WriteMessage(websocket.BinaryMessage, []byte("ready"))
case 3:
spin.Stop()
// unmarshal the file info
log.Debugf("[%d] recieve file info", step)
// do decryption on the file stats
enc, err := crypt.FromBytes(message)
if err != nil {
return err
}
decryptedFileData, err := enc.Decrypt(sessionKey)
if err != nil {
return err
}
err = json.Unmarshal(decryptedFileData, &fstats)
if err != nil {
return err
}
log.Debugf("got file stats: %+v", fstats)
// determine if the file is resuming or not
progressFile = fmt.Sprintf("%s.progress", fstats.SentName)
overwritingOrReceiving := "Receiving"
if utils.Exists(fstats.Name) || utils.Exists(fstats.SentName) {
overwritingOrReceiving = "Overwriting"
if utils.Exists(progressFile) {
overwritingOrReceiving = "Resume receiving"
resumeFile = true
}
}
// send blocks
if resumeFile {
fileWithBlocks, _ := os.Open(progressFile)
scanner := bufio.NewScanner(fileWithBlocks)
for scanner.Scan() {
blocks = append(blocks, strings.TrimSpace(scanner.Text()))
}
fileWithBlocks.Close()
}
blocksBytes, _ := json.Marshal(blocks)
// encrypt the block data and send
encblockBytes := crypt.Encrypt(blocksBytes, sessionKey)
c.WriteMessage(websocket.BinaryMessage, encblockBytes.Bytes())
// prompt user about the file
fileOrFolder := "file"
if fstats.IsDir {
fileOrFolder = "folder"
}
fmt.Fprintf(os.Stderr, "\r%s %s (%s) into: %s\n",
overwritingOrReceiving,
fileOrFolder,
humanize.Bytes(uint64(fstats.Size)),
fstats.Name,
)
if !noPrompt {
if "y" != utils.GetInput("ok? (y/N): ") {
fmt.Fprintf(os.Stderr, "cancelling request")
c.WriteMessage(websocket.BinaryMessage, []byte("no"))
return nil
}
}
// await file
// erase file if overwriting
if overwritingOrReceiving == "Overwriting" {
os.Remove(fstats.SentName)
}
var f *os.File
if utils.Exists(fstats.SentName) && resumeFile {
if !useWebsockets {
f, err = os.OpenFile(fstats.SentName, os.O_WRONLY, 0644)
} else {
f, err = os.OpenFile(fstats.SentName, os.O_APPEND|os.O_WRONLY, 0644)
}
if err != nil {
log.Error(err)
return err
}
} else {
f, err = os.Create(fstats.SentName)
if err != nil {
log.Error(err)
return err
}
if !useWebsockets {
if err = f.Truncate(fstats.Size); err != nil {
log.Error(err)
return err
}
}
}
blockSize := 0
if useWebsockets {
blockSize = models.WEBSOCKET_BUFFER_SIZE / 8
} else {
blockSize = models.TCP_BUFFER_SIZE / 2
}
// start the ui for pgoress
bytesWritten := 0
fmt.Fprintf(os.Stderr, "\nReceiving (<-%s)...\n", otherIP)
bar := progressbar.NewOptions(
int(fstats.Size),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionSetBytes(int(fstats.Size)),
progressbar.OptionSetWriter(os.Stderr),
)
bar.Add((len(blocks) * blockSize))
finished := make(chan bool)
go func(finished chan bool, dataChan chan []byte) (err error) {
// remove previous progress
var fProgress *os.File
var progressErr error
if resumeFile {
fProgress, progressErr = os.OpenFile(progressFile, os.O_APPEND|os.O_WRONLY, 0644)
bytesWritten = len(blocks) * blockSize
} else {
os.Remove(progressFile)
fProgress, progressErr = os.Create(progressFile)
}
if progressErr != nil {
panic(progressErr)
}
defer fProgress.Close()
blocksWritten := 0.0
blocksToWrite := float64(fstats.Size)
if useWebsockets {
blocksToWrite = blocksToWrite/float64(models.WEBSOCKET_BUFFER_SIZE/8) - float64(len(blocks))
} else {
blocksToWrite = blocksToWrite/float64(models.TCP_BUFFER_SIZE/2) - float64(len(blocks))
}
for {
message := <-dataChan
// do decryption
var enc crypt.Encryption
err = json.Unmarshal(message, &enc)
if err != nil {
// log.Errorf("%s: [%s] [%+v] (%d/%d) %+v", err.Error(), message, message, len(message), numBytes, bs)
log.Error(err)
return err
}
decrypted, err := enc.Decrypt(sessionKey, !fstats.IsEncrypted)
if err != nil {
log.Error(err)
return err
}
// get location if TCP
var locationToWrite int
if !useWebsockets {
pieces := bytes.SplitN(decrypted, []byte("-"), 2)
decrypted = pieces[1]
locationToWrite, _ = strconv.Atoi(string(pieces[0]))
}
// do decompression
if fstats.IsCompressed && !fstats.IsDir {
decrypted = compress.Decompress(decrypted)
}
var n int
if !useWebsockets {
if err != nil {
log.Error(err)
return err
}
n, err = f.WriteAt(decrypted, int64(locationToWrite))
fProgress.WriteString(fmt.Sprintf("%d\n", locationToWrite))
log.Debugf("wrote %d bytes to location %d (%2.0f/%2.0f)", n, locationToWrite, blocksWritten, blocksToWrite)
} else {
// write to file
n, err = f.Write(decrypted)
log.Debugf("wrote %d bytes to location %d (%2.0f/%2.0f)", n, bytesWritten, blocksWritten, blocksToWrite)
fProgress.WriteString(fmt.Sprintf("%d\n", bytesWritten))
}
if err != nil {
log.Error(err)
return err
}
// update the bytes written
bytesWritten += n
blocksWritten += 1.0
// update the progress bar
bar.Add(n)
if int64(bytesWritten) == fstats.Size || blocksWritten >= blocksToWrite {
log.Debug("finished", int64(bytesWritten), fstats.Size, blocksWritten, blocksToWrite)
break
}
}
finished <- true
return
}(finished, dataChan)
log.Debug("telling sender i'm ready")
c.WriteMessage(websocket.BinaryMessage, append([]byte("ready"), blocksBytes...))
startTime := time.Now()
if useWebsockets {
for {
var messageType int
// read from websockets
messageType, message, err = c.ReadMessage()
if messageType != websocket.BinaryMessage {
continue
}
if err != nil {
log.Error(err)
return err
}
if bytes.Equal(message, []byte("magic")) {
log.Debug("got magic")
break
}
dataChan <- message
// select {
// case dataChan <- message:
// default:
// log.Debug("blocked")
// // no message sent
// // block
// dataChan <- message
// }
}
} else {
_ = <-isConnectedIfUsingTCP
log.Debugf("starting listening with tcp with %d connections", len(tcpConnections))
// using TCP
var wg sync.WaitGroup
wg.Add(len(tcpConnections))
for i := range tcpConnections {
defer func(i int) {
log.Debugf("closing connection %d", i)
tcpConnections[i].Close()
}(i)
go func(wg *sync.WaitGroup, j int) {
defer wg.Done()
for {
log.Debugf("waiting to read on %d", j)
// read from TCP connection
message, _, _, err := tcpConnections[j].Read()
// log.Debugf("message: %s", message)
if err != nil {
panic(err)
}
if bytes.Equal(message, []byte("magic")) {
log.Debugf("%d got magic, leaving", j)
return
}
dataChan <- message
}
}(&wg, i)
}
wg.Wait()
}
_ = <-finished
log.Debug("telling sender i'm done")
c.WriteMessage(websocket.BinaryMessage, []byte("done"))
// we are finished
transferTime = time.Since(startTime)
// close file
err = f.Close()
if err != nil {
return err
}
// finish bar
bar.Finish()
// check hash
hash256, err = utils.HashFile(fstats.SentName)
if err != nil {
log.Error(err)
return err
}
// tell the sender the hash so they can quit
c.WriteMessage(websocket.BinaryMessage, append([]byte("hash:"), hash256...))
case 4:
// receive the hash from the sender so we can check it and quit
log.Debugf("got hash: %x", message)
if bytes.Equal(hash256, message) {
// open directory
if fstats.IsDir {
err = zipper.UnzipFile(fstats.SentName, ".")
if DebugLevel != "debug" {
os.Remove(fstats.SentName)
}
} else {
err = nil
}
if err == nil {
if useStdout && !fstats.IsDir {
var bFile []byte
bFile, err = ioutil.ReadFile(fstats.SentName)
if err != nil {
return err
}
os.Stdout.Write(bFile)
os.Remove(fstats.SentName)
}
transferRate := float64(fstats.Size) / 1000000.0 / transferTime.Seconds()
transferType := "MB/s"
if transferRate < 1 {
transferRate = float64(fstats.Size) / 1000.0 / transferTime.Seconds()
transferType = "kB/s"
}
folderOrFile := "file"
if fstats.IsDir {
folderOrFile = "folder"
}
if useStdout {
fstats.Name = "stdout"
}
fmt.Fprintf(os.Stderr, "\nReceived %s written to %s (%2.1f %s)\n", folderOrFile, fstats.Name, transferRate, transferType)
os.Remove(progressFile)
}
return err
} else {
if DebugLevel != "debug" {
log.Debug("removing corrupted file")
os.Remove(fstats.SentName)
}
return errors.New("file corrupted")
}
default:
return fmt.Errorf("unknown step")
}
step++
}
}
func connectToTCPServer(room string, address string) (com comm.Comm, err error) {
log.Debugf("recipient connecting to %s", address)
connection, err := net.Dial("tcp", address)
if err != nil {
return
}
connection.SetReadDeadline(time.Now().Add(3 * time.Hour))
connection.SetDeadline(time.Now().Add(3 * time.Hour))
connection.SetWriteDeadline(time.Now().Add(3 * time.Hour))
com = comm.New(connection)
log.Debug("waiting for server contact")
ok, err := com.Receive()
if err != nil {
return
}
log.Debugf("[%s] server says: %s", address, ok)
err = com.Send(room)
if err != nil {
return
}
ok, err = com.Receive()
log.Debugf("[%s] server says: %s", address, ok)
if err != nil {
return
}
if ok != "recipient" {
err = errors.New(ok)
}
return
}

View File

@ -1,123 +0,0 @@
package relay
import (
"net/http"
"time"
log "github.com/cihub/seelog"
"github.com/gorilla/websocket"
"github.com/schollz/croc/src/models"
)
const (
// Time allowed to write a message to the peer.
writeWait = 6000 * time.Second
// Time allowed to read the next pong message from the peer.
pongWait = 6000 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum message size allowed from peer.
maxMessageSize = models.WEBSOCKET_BUFFER_SIZE / 2
)
var upgrader = websocket.Upgrader{
ReadBufferSize: models.WEBSOCKET_BUFFER_SIZE,
WriteBufferSize: models.WEBSOCKET_BUFFER_SIZE,
}
// connection is an middleman between the websocket connection and the hub.
type connection struct {
// The websocket connection.
ws *websocket.Conn
// Buffered channel of outbound messages.
send chan messageChannel
}
type messageChannel struct {
data []byte
messageType int
}
// readPump pumps messages from the websocket connection to the hub.
func (s subscription) readPump() {
c := s.conn
defer func() {
h.unregister <- s
c.ws.Close()
}()
c.ws.SetReadLimit(maxMessageSize)
c.ws.SetReadDeadline(time.Now().Add(pongWait))
c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
for {
messageType, msg, err := c.ws.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Debugf("unexpected close: %v", err)
}
break
}
h.broadcast <- message{messageChannel{msg, messageType}, s.room, c.ws.RemoteAddr().String()}
}
}
// write writes a message with the given message type and payload.
func (c *connection) write(mt int, payload []byte) error {
c.ws.SetWriteDeadline(time.Now().Add(writeWait))
return c.ws.WriteMessage(mt, payload)
}
// writePump pumps messages from the hub to the websocket connection.
func (s *subscription) writePump() {
c := s.conn
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
c.ws.Close()
}()
for {
select {
case message, ok := <-c.send:
if !ok {
err := c.write(websocket.CloseMessage, []byte{})
if err != nil {
log.Debug(err)
}
return
}
if err := c.write(message.messageType, message.data); err != nil {
log.Debug(err)
return
}
case <-ticker.C:
if err := c.write(websocket.PingMessage, []byte{}); err != nil {
log.Debug(err)
return
}
}
}
}
// serveWs handles websocket requests from the peer.
func serveWs(w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Debug(err)
return
}
vals := r.URL.Query()
room := "default"
rooms, ok := vals["room"]
if ok {
room = rooms[0]
}
c := &connection{send: make(chan messageChannel, 256), ws: ws}
s := subscription{c, room}
h.register <- s
go s.writePump()
s.readPump()
}

View File

@ -1,101 +0,0 @@
package relay
import (
"sync"
log "github.com/cihub/seelog"
)
type message struct {
msg messageChannel
room string
remoteOrigin string
}
type subscription struct {
conn *connection
room string
}
// hub maintains the set of active connections and broadcasts messages to the
// connections.
type hub struct {
// Registered connections.
rooms roomMap
// Inbound messages from the connections.
broadcast chan message
// Register requests from the connections.
register chan subscription
// Unregister requests from connections.
unregister chan subscription
}
type roomMap struct {
rooms map[string]map[*connection]bool
sync.Mutex
}
var h = hub{
broadcast: make(chan message),
register: make(chan subscription),
unregister: make(chan subscription),
rooms: roomMap{rooms: make(map[string]map[*connection]bool)},
}
func (h *hub) run() {
for {
select {
case s := <-h.register:
log.Debugf("adding connection to %s", s.room)
h.rooms.Lock()
connections := h.rooms.rooms[s.room]
if connections == nil {
connections = make(map[*connection]bool)
h.rooms.rooms[s.room] = connections
}
h.rooms.rooms[s.room][s.conn] = true
if len(h.rooms.rooms) > 2 {
// if more than three, close all of them
for connection := range h.rooms.rooms[s.room] {
close(connection.send)
}
log.Debugf("deleting room %s", s.room)
delete(h.rooms.rooms, s.room)
}
h.rooms.Unlock()
case s := <-h.unregister:
// if one leaves, close all of them
h.rooms.Lock()
if _, ok := h.rooms.rooms[s.room]; ok {
for connection := range h.rooms.rooms[s.room] {
close(connection.send)
}
log.Debugf("deleting room %s", s.room)
delete(h.rooms.rooms, s.room)
}
h.rooms.Unlock()
case m := <-h.broadcast:
h.rooms.Lock()
connections := h.rooms.rooms[m.room]
for c := range connections {
if c.ws.RemoteAddr().String() == m.remoteOrigin {
continue
}
select {
case c.send <- m.msg:
default:
close(c.send)
delete(connections, c)
if len(connections) == 0 {
log.Debugf("deleting room %s", m.room)
delete(h.rooms.rooms, m.room)
}
}
}
h.rooms.Unlock()
}
}
}

View File

@ -1,34 +0,0 @@
package relay
import (
"fmt"
"net/http"
log "github.com/cihub/seelog"
"github.com/schollz/croc/src/logger"
"github.com/schollz/croc/src/tcp"
)
var DebugLevel string
// Run is the async operation for running a server
func Run(port string, tcpPorts []string) (err error) {
logger.SetLogLevel(DebugLevel)
if len(tcpPorts) > 0 {
for _, tcpPort := range tcpPorts {
go tcp.Run(DebugLevel, tcpPort)
}
}
go h.run()
log.Debug("running relay on " + port)
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
serveWs(w, r)
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "ok")
})
err = http.ListenAndServe(":"+port, nil)
return
}

View File

@ -1,491 +0,0 @@
package sender
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
log "github.com/cihub/seelog"
"github.com/gorilla/websocket"
"github.com/pkg/errors"
"github.com/schollz/croc/src/comm"
"github.com/schollz/croc/src/compress"
"github.com/schollz/croc/src/crypt"
"github.com/schollz/croc/src/logger"
"github.com/schollz/croc/src/models"
"github.com/schollz/croc/src/utils"
"github.com/schollz/croc/src/zipper"
"github.com/schollz/pake"
"github.com/schollz/progressbar/v2"
"github.com/schollz/spinner"
"github.com/tscholl2/siec"
)
var DebugLevel string
// Send is the async call to send data
func Send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, done chan struct{}, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) {
logger.SetLogLevel(DebugLevel)
log.Debugf("sending %s", fname)
err := send(forceSend, serverAddress, tcpPorts, isLocal, c, fname, codephrase, useCompression, useEncryption)
if err != nil {
if !strings.HasPrefix(err.Error(), "websocket: close 100") {
fmt.Fprintf(os.Stderr, "\n"+err.Error())
}
}
done <- struct{}{}
}
func send(forceSend int, serverAddress string, tcpPorts []string, isLocal bool, c *websocket.Conn, fname string, codephrase string, useCompression bool, useEncryption bool) (err error) {
var f *os.File
defer f.Close() // ignore the error if it wasn't opened :(
var fstats models.FileStats
var fileHash []byte
var otherIP string
var startTransfer time.Time
var tcpConnections []comm.Comm
blocksToSkip := make(map[int64]struct{})
isConnectedIfUsingTCP := make(chan bool)
type DataChan struct {
b []byte
currentPostition int64
bytesRead int
err error
}
dataChan := make(chan DataChan, 1024*1024)
defer close(dataChan)
useWebsockets := true
switch forceSend {
case 0:
if !isLocal {
useWebsockets = false
}
case 1:
useWebsockets = true
case 2:
useWebsockets = false
}
fileReady := make(chan error)
// normalize the file name
fname, err = filepath.Abs(fname)
if err != nil {
return err
}
_, filename := filepath.Split(fname)
// get ready to generate session key
var sessionKey []byte
// start a spinner
spin := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
spin.Writer = os.Stderr
// pick an elliptic curve
curve := siec.SIEC255()
// both parties should have a weak key
pw := []byte(codephrase)
// initialize sender P ("0" indicates sender)
P, err := pake.Init(pw, 0, curve, 1*time.Millisecond)
if err != nil {
return
}
step := 0
for {
messageType, message, errRead := c.ReadMessage()
if errRead != nil {
return errRead
}
if messageType == websocket.PongMessage || messageType == websocket.PingMessage {
continue
}
if messageType == websocket.TextMessage && bytes.Equal(message, []byte("interrupt")) {
return errors.New("\rinterrupted by other party")
}
log.Debugf("got %d: %s", messageType, message)
switch step {
case 0:
// sender initiates communication
ip := ""
if isLocal {
ip = utils.LocalIP()
} else {
ip, _ = utils.PublicIP()
}
// send my IP address
c.WriteMessage(websocket.BinaryMessage, []byte(ip))
case 1:
// first receive the IP address from the sender
otherIP = string(message)
log.Debugf("recipient IP: %s", otherIP)
go func() {
// recipient might want file! start gathering information about file
fstat, err := os.Stat(fname)
if err != nil {
fileReady <- err
return
}
fstats = models.FileStats{
Name: filename,
Size: fstat.Size(),
ModTime: fstat.ModTime(),
IsDir: fstat.IsDir(),
SentName: fstat.Name(),
IsCompressed: useCompression,
IsEncrypted: useEncryption,
}
if fstats.IsDir {
// zip the directory
fstats.SentName, err = zipper.ZipFile(fname, true)
if err != nil {
log.Error(err)
fileReady <- err
return
}
fname = fstats.SentName
fstat, err := os.Stat(fname)
if err != nil {
fileReady <- err
return
}
// get new size
fstats.Size = fstat.Size()
}
// open the file
f, err = os.Open(fname)
if err != nil {
fileReady <- err
return
}
fileReady <- nil
}()
// send pake data
log.Debugf("[%d] first, P sends u to Q", step)
c.WriteMessage(websocket.BinaryMessage, P.Bytes())
// start PAKE spinnner
spin.Suffix = " performing PAKE..."
spin.Start()
case 2:
// P recieves H(k),v from Q
log.Debugf("[%d] P computes k, H(k), sends H(k) to Q", step)
if err := P.Update(message); err != nil {
return err
}
c.WriteMessage(websocket.BinaryMessage, P.Bytes())
sessionKey, _ = P.SessionKey()
// check(err)
log.Debugf("%x\n", sessionKey)
// wait for readiness
spin.Stop()
spin.Suffix = " waiting for recipient ok..."
spin.Start()
case 3:
log.Debugf("[%d] recipient declares readiness for file info", step)
if !bytes.HasPrefix(message, []byte("ready")) {
return errors.New("recipient refused file")
}
// connect to TCP in background
tcpConnections = make([]comm.Comm, len(tcpPorts))
go func() {
if !useWebsockets {
log.Debugf("connecting to server")
for i, tcpPort := range tcpPorts {
log.Debugf("connecting to %s on connection %d", tcpPort, i)
tcpConnections[i], err = connectToTCPServer(utils.SHA256(fmt.Sprintf("%d%x", i, sessionKey)), serverAddress+":"+tcpPort)
if err != nil {
log.Error(err)
}
}
}
isConnectedIfUsingTCP <- true
}()
err = <-fileReady // block until file is ready
if err != nil {
return err
}
fstatsBytes, err := json.Marshal(fstats)
if err != nil {
return err
}
// encrypt the file meta data
enc := crypt.Encrypt(fstatsBytes, sessionKey)
// send the file meta data
c.WriteMessage(websocket.BinaryMessage, enc.Bytes())
case 4:
log.Debugf("[%d] recipient declares gives blocks", step)
// recipient sends blocks, and sender does not send anything back
// determine if any blocks were sent to skip
enc, err := crypt.FromBytes(message)
if err != nil {
log.Error(err)
return err
}
decrypted, err := enc.Decrypt(sessionKey)
if err != nil {
err = errors.Wrap(err, "could not decrypt blocks with session key")
log.Error(err)
return err
}
var blocks []string
errBlocks := json.Unmarshal(decrypted, &blocks)
if errBlocks == nil {
for _, block := range blocks {
blockInt64, errBlock := strconv.Atoi(block)
if errBlock == nil {
blocksToSkip[int64(blockInt64)] = struct{}{}
}
}
}
log.Debugf("found blocks: %+v", blocksToSkip)
// start loading the file into memory
// start streaming encryption/compression
if fstats.IsDir {
// remove file if zipped
defer os.Remove(fstats.SentName)
}
go func(dataChan chan DataChan) {
var buffer []byte
if useWebsockets {
buffer = make([]byte, models.WEBSOCKET_BUFFER_SIZE/8)
} else {
buffer = make([]byte, models.TCP_BUFFER_SIZE/2)
}
currentPostition := int64(0)
for {
bytesread, err := f.Read(buffer)
if bytesread > 0 {
if _, ok := blocksToSkip[currentPostition]; ok {
log.Debugf("skipping the sending of block %d", currentPostition)
currentPostition += int64(bytesread)
continue
}
// do compression
var compressedBytes []byte
if useCompression && !fstats.IsDir {
compressedBytes = compress.Compress(buffer[:bytesread])
} else {
compressedBytes = buffer[:bytesread]
}
// if using TCP, prepend the location to write the data to in the resulting file
if !useWebsockets {
compressedBytes = append([]byte(fmt.Sprintf("%d-", currentPostition)), compressedBytes...)
}
// do encryption
enc := crypt.Encrypt(compressedBytes, sessionKey, !useEncryption)
encBytes, err := json.Marshal(enc)
if err != nil {
dataChan <- DataChan{
b: nil,
bytesRead: 0,
err: err,
}
return
}
dataChan <- DataChan{
b: encBytes,
bytesRead: bytesread,
err: nil,
}
currentPostition += int64(bytesread)
}
if err != nil {
if err != io.EOF {
log.Error(err)
}
break
}
}
// finish
log.Debug("sending magic")
dataChan <- DataChan{
b: []byte("magic"),
bytesRead: 0,
err: nil,
}
if !useWebsockets {
log.Debug("sending extra magic to %d others", len(tcpPorts)-1)
for i := 0; i < len(tcpPorts)-1; i++ {
log.Debug("sending magic")
dataChan <- DataChan{
b: []byte("magic"),
bytesRead: 0,
err: nil,
}
}
}
}(dataChan)
case 5:
spin.Stop()
log.Debugf("[%d] recipient declares readiness for file data", step)
if !bytes.HasPrefix(message, []byte("ready")) {
return errors.New("recipient refused file")
}
fmt.Fprintf(os.Stderr, "\rSending (->%s)...\n", otherIP)
// send file, compure hash simultaneously
startTransfer = time.Now()
blockSize := 0
if useWebsockets {
blockSize = models.WEBSOCKET_BUFFER_SIZE / 8
} else {
blockSize = models.TCP_BUFFER_SIZE / 2
}
bar := progressbar.NewOptions(
int(fstats.Size),
progressbar.OptionSetRenderBlankState(true),
progressbar.OptionSetBytes(int(fstats.Size)),
progressbar.OptionSetWriter(os.Stderr),
)
bar.Add(blockSize * len(blocksToSkip))
if useWebsockets {
for {
data := <-dataChan
if data.err != nil {
return data.err
}
bar.Add(data.bytesRead)
// write data to websockets
err = c.WriteMessage(websocket.BinaryMessage, data.b)
if err != nil {
err = errors.Wrap(err, "problem writing message")
return err
}
if bytes.Equal(data.b, []byte("magic")) {
break
}
}
} else {
_ = <-isConnectedIfUsingTCP
log.Debug("connected and ready to send on tcp")
var wg sync.WaitGroup
wg.Add(len(tcpConnections))
for i := range tcpConnections {
defer func(i int) {
log.Debugf("closing connection %d", i)
tcpConnections[i].Close()
}(i)
go func(i int, wg *sync.WaitGroup, dataChan <-chan DataChan) {
defer wg.Done()
for data := range dataChan {
if data.err != nil {
log.Error(data.err)
return
}
bar.Add(data.bytesRead)
// write data to tcp connection
_, err = tcpConnections[i].Write(data.b)
if err != nil {
err = errors.Wrap(err, "problem writing message")
log.Error(err)
return
}
if bytes.Equal(data.b, []byte("magic")) {
log.Debugf("%d got magic", i)
return
}
}
}(i, &wg, dataChan)
}
wg.Wait()
}
bar.Finish()
log.Debug("send hash to finish file")
fileHash, err = utils.HashFile(fname)
if err != nil {
return err
}
case 6:
// recevied something, maybe the file hash
transferTime := time.Since(startTransfer)
if !bytes.HasPrefix(message, []byte("hash:")) {
log.Debugf("%s", message)
continue
}
c.WriteMessage(websocket.BinaryMessage, fileHash)
message = bytes.TrimPrefix(message, []byte("hash:"))
log.Debugf("[%d] determing whether it went ok", step)
if bytes.Equal(message, fileHash) {
log.Debug("file transfered successfully")
transferRate := float64(fstats.Size) / 1000000.0 / transferTime.Seconds()
transferType := "MB/s"
if transferRate < 1 {
transferRate = float64(fstats.Size) / 1000.0 / transferTime.Seconds()
transferType = "kB/s"
}
fmt.Fprintf(os.Stderr, "\nTransfer complete (%2.1f %s)", transferRate, transferType)
return nil
} else {
fmt.Fprintf(os.Stderr, "\nTransfer corrupted")
return errors.New("file not transfered succesfully")
}
default:
return fmt.Errorf("unknown step")
}
step++
}
}
func connectToTCPServer(room string, address string) (com comm.Comm, err error) {
connection, err := net.DialTimeout("tcp", address, 3*time.Hour)
if err != nil {
return
}
connection.SetReadDeadline(time.Now().Add(3 * time.Hour))
connection.SetDeadline(time.Now().Add(3 * time.Hour))
connection.SetWriteDeadline(time.Now().Add(3 * time.Hour))
com = comm.New(connection)
ok, err := com.Receive()
if err != nil {
return
}
log.Debugf("server says: %s", ok)
err = com.Send(room)
if err != nil {
return
}
ok, err = com.Receive()
log.Debugf("server says: %s", ok)
if err != nil {
return
}
if ok != "sender" {
err = errors.New(ok)
}
return
}

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

@ -1,20 +1,40 @@
package tcp
import (
"bytes"
"fmt"
"net"
"strings"
"sync"
"time"
log "github.com/cihub/seelog"
"github.com/pkg/errors"
"github.com/schollz/croc/src/comm"
"github.com/schollz/croc/src/logger"
"github.com/schollz/croc/src/models"
log "github.com/schollz/logger"
"github.com/schollz/pake/v3"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/crypt"
"github.com/schollz/croc/v10/src/models"
)
type server struct {
host string
port string
debugLevel string
banner string
password string
rooms roomMap
roomCleanupInterval time.Duration
roomTTL time.Duration
stopRoomCleanup chan struct{}
}
type roomInfo struct {
receiver comm.Comm
opened time.Time
first *comm.Comm
second *comm.Comm
opened time.Time
full bool
}
type roomMap struct {
@ -22,129 +42,375 @@ type roomMap struct {
sync.Mutex
}
var rooms roomMap
const pingRoom = "pinglkasjdlfjsaldjf"
// 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
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, port string) {
logger.SetLogLevel(debugLevel)
rooms.Lock()
rooms.rooms = make(map[string]roomInfo)
rooms.Unlock()
func Run(debugLevel, host, port, password string, banner ...string) (err error) {
return RunWithOptionsAsync(host, port, password, WithBanner(banner...), WithLogLevel(debugLevel))
}
// delete old rooms
go func() {
for {
time.Sleep(10 * time.Minute)
rooms.Lock()
for room := range rooms.rooms {
if time.Since(rooms.rooms[room].opened) > 3*time.Hour {
delete(rooms.rooms, room)
}
}
rooms.Unlock()
}
}()
func (s *server) start() (err error) {
log.SetLevel(s.debugLevel)
err := run(port)
// 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()
go s.deleteOldRooms()
defer s.stopRoomDeletion()
err = s.run()
if err != nil {
log.Error(err)
}
return
}
func run(port string) (err error) {
log.Debugf("starting TCP server on " + port)
server, err := net.Listen("tcp", "0.0.0.0:"+port)
func (s *server) run() (err error) {
network := "tcp"
addr := net.JoinHostPort(s.host, s.port)
if s.host != "" {
ip := net.ParseIP(s.host)
if ip == nil {
var tcpIP *net.IPAddr
tcpIP, err = net.ResolveIPAddr("ip", s.host)
if err != nil {
return err
}
ip = tcpIP.IP
}
addr = net.JoinHostPort(ip.String(), s.port)
if s.host != "" {
if ip.To4() != nil {
network = "tcp4"
} else {
network = "tcp6"
}
}
}
addr = strings.Replace(addr, "127.0.0.1", "0.0.0.0", 1)
log.Infof("starting TCP server on " + addr)
server, err := net.Listen(network, addr)
if err != nil {
return errors.Wrap(err, "Error listening on :"+port)
return fmt.Errorf("error listening on %s: %w", addr, err)
}
defer server.Close()
// spawn a new goroutine whenever a client connects
for {
connection, err := server.Accept()
if err != nil {
return errors.Wrap(err, "problem accepting connection")
return fmt.Errorf("problem accepting connection: %w", err)
}
log.Debugf("client %s connected", connection.RemoteAddr().String())
go func(port string, connection net.Conn) {
errCommunication := clientCommuncation(port, comm.New(connection))
c := comm.New(connection)
room, errCommunication := s.clientCommunication(port, c)
log.Debugf("room: %+v", room)
log.Debugf("err: %+v", errCommunication)
if errCommunication != nil {
log.Warnf("relay-%s: %s", connection.RemoteAddr().String(), errCommunication.Error())
log.Debugf("relay-%s: %s", connection.RemoteAddr().String(), errCommunication.Error())
connection.Close()
return
}
}(port, connection)
if room == pingRoom {
log.Debugf("got ping")
connection.Close()
return
}
for {
// check connection
log.Debugf("checking connection of room %s for %+v", room, c)
deleteIt := false
s.rooms.Lock()
if _, ok := s.rooms.rooms[room]; !ok {
log.Debug("room is gone")
s.rooms.Unlock()
return
}
log.Debugf("room: %+v", s.rooms.rooms[room])
if s.rooms.rooms[room].first != nil && s.rooms.rooms[room].second != nil {
log.Debug("rooms ready")
s.rooms.Unlock()
break
} else {
if s.rooms.rooms[room].first != nil {
errSend := s.rooms.rooms[room].first.Send([]byte{1})
if errSend != nil {
log.Debug(errSend)
deleteIt = true
}
}
}
s.rooms.Unlock()
if deleteIt {
s.deleteRoom(room)
break
}
time.Sleep(1 * time.Second)
}
}(s.port, connection)
}
}
func clientCommuncation(port string, c comm.Comm) (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) {
// establish secure password with PAKE for communication with relay
B, err := pake.InitCurve(weakKey, 1, "siec")
if err != nil {
return
}
Abytes, err := c.Receive()
if err != nil {
return
}
log.Debugf("Abytes: %s", Abytes)
if bytes.Equal(Abytes, []byte("ping")) {
room = pingRoom
log.Debug("sending back pong")
c.Send([]byte("pong"))
return
}
err = B.Update(Abytes)
if err != nil {
return
}
err = c.Send(B.Bytes())
if err != nil {
return
}
strongKey, err := B.SessionKey()
if err != nil {
return
}
log.Debugf("strongkey: %x", strongKey)
// receive salt
salt, err := c.Receive()
if err != nil {
return
}
strongKeyForEncryption, _, err := crypt.New(strongKey, salt)
if err != nil {
return
}
log.Debugf("waiting for password")
passwordBytesEnc, err := c.Receive()
if err != nil {
return
}
passwordBytes, err := crypt.Decrypt(passwordBytesEnc, strongKeyForEncryption)
if err != nil {
return
}
if strings.TrimSpace(string(passwordBytes)) != s.password {
err = fmt.Errorf("bad password")
enc, _ := crypt.Encrypt([]byte(err.Error()), strongKeyForEncryption)
if err = c.Send(enc); err != nil {
return "", fmt.Errorf("send error: %w", err)
}
return
}
// send ok to tell client they are connected
log.Debug("sending ok")
err = c.Send("ok")
banner := s.banner
if len(banner) == 0 {
banner = "ok"
}
log.Debugf("sending '%s'", banner)
bSend, err := crypt.Encrypt([]byte(banner+"|||"+c.Connection().RemoteAddr().String()), strongKeyForEncryption)
if err != nil {
return
}
err = c.Send(bSend)
if err != nil {
return
}
// wait for client to tell me which room they want
log.Debug("waiting for answer")
room, err := c.Receive()
enc, err := c.Receive()
if err != nil {
return
}
roomBytes, err := crypt.Decrypt(enc, strongKeyForEncryption)
if err != nil {
return
}
room = string(roomBytes)
rooms.Lock()
// first connection is always the receiver
if _, ok := rooms.rooms[room]; !ok {
rooms.rooms[room] = roomInfo{
receiver: c,
opened: time.Now(),
s.rooms.Lock()
// create the room if it is new
if _, ok := s.rooms.rooms[room]; !ok {
s.rooms.rooms[room] = roomInfo{
first: c,
opened: time.Now(),
}
rooms.Unlock()
s.rooms.Unlock()
// tell the client that they got the room
err = c.Send("recipient")
bSend, err = crypt.Encrypt([]byte("ok"), strongKeyForEncryption)
if err != nil {
return
}
err = c.Send(bSend)
if err != nil {
log.Error(err)
s.deleteRoom(room)
return
}
log.Debugf("room %s has 1", room)
return
}
if s.rooms.rooms[room].full {
s.rooms.Unlock()
bSend, err = crypt.Encrypt([]byte("room full"), strongKeyForEncryption)
if err != nil {
return
}
err = c.Send(bSend)
if err != nil {
log.Error(err)
return
}
log.Debug("recipient connected")
return nil
return
}
log.Debug("sender connected")
receiver := rooms.rooms[room].receiver
rooms.Unlock()
log.Debugf("room %s has 2", room)
s.rooms.rooms[room] = roomInfo{
first: s.rooms.rooms[room].first,
second: c,
opened: s.rooms.rooms[room].opened,
full: true,
}
otherConnection := s.rooms.rooms[room].first
s.rooms.Unlock()
// second connection is the sender, time to staple connections
var wg sync.WaitGroup
wg.Add(1)
// start piping
go func(com1, com2 comm.Comm, wg *sync.WaitGroup) {
go func(com1, com2 *comm.Comm, wg *sync.WaitGroup) {
log.Debug("starting pipes")
pipe(com1.Connection(), com2.Connection())
wg.Done()
log.Debug("done piping")
}(c, receiver, &wg)
}(otherConnection, c, &wg)
// tell the sender everything is ready
err = c.Send("sender")
bSend, err = crypt.Encrypt([]byte("ok"), strongKeyForEncryption)
if err != nil {
return
}
err = c.Send(bSend)
if err != nil {
s.deleteRoom(room)
return
}
wg.Wait()
// delete room
rooms.Lock()
s.deleteRoom(room)
return
}
func (s *server) deleteRoom(room string) {
s.rooms.Lock()
defer s.rooms.Unlock()
if _, ok := s.rooms.rooms[room]; !ok {
return
}
log.Debugf("deleting room: %s", room)
delete(rooms.rooms, room)
rooms.Unlock()
return nil
if s.rooms.rooms[room].first != nil {
s.rooms.rooms[room].first.Close()
}
if s.rooms.rooms[room].second != nil {
s.rooms.rooms[room].second.Close()
}
s.rooms.rooms[room] = roomInfo{first: nil, second: nil}
delete(s.rooms.rooms, room)
}
// chanFromConn creates a channel from a Conn object, and sends everything it
// Read()s from the socket to the channel.
//
// Read()s from the socket to the channel.
func chanFromConn(conn net.Conn) chan []byte {
c := make(chan []byte)
c := make(chan []byte, 1)
if err := conn.SetReadDeadline(time.Now().Add(3 * time.Hour)); err != nil {
log.Warnf("can't set read deadline: %v", err)
}
go func() {
b := make([]byte, models.TCP_BUFFER_SIZE)
for {
n, err := conn.Read(b)
if n > 0 {
@ -159,6 +425,7 @@ func chanFromConn(conn net.Conn) chan []byte {
break
}
}
log.Debug("exiting")
}()
return c
@ -176,13 +443,153 @@ func pipe(conn1 net.Conn, conn2 net.Conn) {
if b1 == nil {
return
}
conn2.Write(b1)
if _, err := conn2.Write(b1); err != nil {
log.Errorf("write error on channel 1: %v", err)
}
case b2 := <-chan2:
if b2 == nil {
return
}
conn1.Write(b2)
if _, err := conn1.Write(b2); err != nil {
log.Errorf("write error on channel 2: %v", err)
}
}
}
}
func PingServer(address string) (err error) {
log.Debugf("pinging %s", address)
c, err := comm.NewConnection(address, 300*time.Millisecond)
if err != nil {
log.Debug(err)
return
}
err = c.Send([]byte("ping"))
if err != nil {
log.Debug(err)
return
}
b, err := c.Receive()
if err != nil {
log.Debug(err)
return
}
if bytes.Equal(b, []byte("pong")) {
return nil
}
return fmt.Errorf("no pong")
}
// ConnectToTCPServer will initiate a new connection
// to the specified address, room with optional time limit
func ConnectToTCPServer(address, password, room string, timelimit ...time.Duration) (c *comm.Comm, banner string, ipaddr string, err error) {
if len(timelimit) > 0 {
c, err = comm.NewConnection(address, timelimit[0])
} else {
c, err = comm.NewConnection(address)
}
if err != nil {
log.Debug(err)
return
}
// get PAKE connection with server to establish strong key to transfer info
A, err := pake.InitCurve(weakKey, 0, "siec")
if err != nil {
log.Debug(err)
return
}
err = c.Send(A.Bytes())
if err != nil {
log.Debug(err)
return
}
Bbytes, err := c.Receive()
if err != nil {
log.Debug(err)
return
}
err = A.Update(Bbytes)
if err != nil {
log.Debug(err)
return
}
strongKey, err := A.SessionKey()
if err != nil {
log.Debug(err)
return
}
log.Debugf("strong key: %x", strongKey)
strongKeyForEncryption, salt, err := crypt.New(strongKey, nil)
if err != nil {
log.Debug(err)
return
}
// send salt
err = c.Send(salt)
if err != nil {
log.Debug(err)
return
}
log.Debug("sending password")
bSend, err := crypt.Encrypt([]byte(password), strongKeyForEncryption)
if err != nil {
log.Debug(err)
return
}
err = c.Send(bSend)
if err != nil {
log.Debug(err)
return
}
log.Debug("waiting for first ok")
enc, err := c.Receive()
if err != nil {
log.Debug(err)
return
}
data, err := crypt.Decrypt(enc, strongKeyForEncryption)
if err != nil {
log.Debug(err)
return
}
if !strings.Contains(string(data), "|||") {
err = fmt.Errorf("bad response: %s", string(data))
log.Debug(err)
return
}
banner = strings.Split(string(data), "|||")[0]
ipaddr = strings.Split(string(data), "|||")[1]
log.Debugf("sending room; %s", room)
bSend, err = crypt.Encrypt([]byte(room), strongKeyForEncryption)
if err != nil {
log.Debug(err)
return
}
err = c.Send(bSend)
if err != nil {
log.Debug(err)
return
}
log.Debug("waiting for room confirmation")
enc, err = c.Receive()
if err != nil {
log.Debug(err)
return
}
data, err = crypt.Decrypt(enc, strongKeyForEncryption)
if err != nil {
log.Debug(err)
return
}
if !bytes.Equal(data, []byte("ok")) {
err = fmt.Errorf("got bad response: %s", data)
log.Debug(err)
return
}
log.Debug("all set")
return
}

71
src/tcp/tcp_test.go Normal file
View File

@ -0,0 +1,71 @@
package tcp
import (
"bytes"
"fmt"
"testing"
"time"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
func BenchmarkConnection(b *testing.B) {
log.SetLevel("trace")
go Run("debug", "127.0.0.1", "8283", "pass123", "8284")
time.Sleep(100 * time.Millisecond)
b.ResetTimer()
for i := 0; i < b.N; i++ {
c, _, _, _ := ConnectToTCPServer("127.0.0.1:8283", "pass123", fmt.Sprintf("testroom%d", i), 1*time.Minute)
c.Close()
}
}
func TestTCP(t *testing.T) {
log.SetLevel("error")
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)
err = PingServer("127.0.0.1:8333")
assert.NotNil(t, err)
time.Sleep(timeToRoomDeletion)
c1, banner, _, err := ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom", 1*time.Minute)
assert.Equal(t, banner, "8382")
assert.Nil(t, err)
c2, _, _, err := ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom")
assert.Nil(t, err)
_, _, _, err = ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom")
assert.NotNil(t, err)
_, _, _, err = ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom", 1*time.Nanosecond)
assert.NotNil(t, err)
// try sending data
assert.Nil(t, c1.Send([]byte("hello, c2")))
var data []byte
for {
data, err = c2.Receive()
if bytes.Equal(data, []byte{1}) {
continue
}
break
}
assert.Nil(t, err)
assert.Equal(t, []byte("hello, c2"), data)
assert.Nil(t, c2.Send([]byte("hello, c1")))
for {
data, err = c1.Receive()
if bytes.Equal(data, []byte{1}) {
continue
}
break
}
assert.Nil(t, err)
assert.Equal(t, []byte("hello, c1"), data)
c1.Close()
time.Sleep(300 * time.Millisecond)
}

View File

@ -1,13 +0,0 @@
package utils
import "os"
// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}

View File

@ -1,15 +0,0 @@
package utils
import (
"bufio"
"fmt"
"os"
"strings"
)
func GetInput(prompt string) string {
reader := bufio.NewReader(os.Stdin)
fmt.Fprintf(os.Stderr, "%s", prompt)
text, _ := reader.ReadString('\n')
return strings.TrimSpace(text)
}

View File

@ -1,33 +0,0 @@
package utils
import (
"crypto/md5"
"crypto/sha256"
"fmt"
"io"
"os"
)
// HashFile returns the md5 hash of a file
func HashFile(fname string) (hash256 []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
}
defer f.Close()
h := md5.New()
if _, err = io.Copy(h, f); err != nil {
return
}
hash256 = h.Sum(nil)
return
}
// SHA256 returns sha256 sum
func SHA256(s string) string {
sha := sha256.New()
sha.Write([]byte(s))
return fmt.Sprintf("%x", sha.Sum(nil))
}

View File

@ -1,39 +0,0 @@
package utils
import (
"io/ioutil"
"log"
"net"
"net/http"
"strings"
)
func PublicIP() (ip string, err error) {
resp, err := http.Get("https://canhazip.com")
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode == http.StatusOK {
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
ip = strings.TrimSpace(string(bodyBytes))
}
return
}
// Get preferred outbound ip of this machine
func LocalIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}

View File

@ -1,11 +0,0 @@
package utils
import (
"fmt"
"testing"
)
func TestGetIP(t *testing.T) {
fmt.Println(PublicIP())
fmt.Println(LocalIP())
}

View File

@ -1,16 +0,0 @@
package utils
import (
"crypto/rand"
"strings"
"github.com/schollz/mnemonicode"
)
func GetRandomName() string {
result := []string{}
bs := make([]byte, 4)
rand.Read(bs)
result = mnemonicode.EncodeWordList(result, bs)
return strings.Join(result, "-")
}

637
src/utils/utils.go Normal file
View File

@ -0,0 +1,637 @@
package utils
import (
"archive/zip"
"bufio"
"bytes"
"compress/flate"
"crypto/md5"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"math"
"math/big"
"net"
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"unicode"
"github.com/cespare/xxhash"
"github.com/kalafut/imohash"
"github.com/minio/highwayhash"
"github.com/schollz/croc/v10/src/mnemonicode"
log "github.com/schollz/logger"
"github.com/schollz/progressbar/v3"
)
const NbPinNumbers = 4
const NbBytesWords = 4
// Get or create home directory
func GetConfigDir(requireValidPath bool) (homedir string, err error) {
if envHomedir, isSet := os.LookupEnv("CROC_CONFIG_DIR"); isSet {
homedir = envHomedir
} else if xdgConfigHome, isSet := os.LookupEnv("XDG_CONFIG_HOME"); isSet {
homedir = path.Join(xdgConfigHome, "croc")
} else {
homedir, err = os.UserHomeDir()
if err != nil {
if !requireValidPath {
err = nil
homedir = ""
}
return
}
homedir = path.Join(homedir, ".config", "croc")
}
if requireValidPath {
if _, err = os.Stat(homedir); os.IsNotExist(err) {
err = os.MkdirAll(homedir, 0o700)
}
}
return
}
// Exists reports whether the named file or directory exists.
func Exists(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// GetInput returns the input with a given prompt
func GetInput(prompt string) string {
reader := bufio.NewReader(os.Stdin)
fmt.Fprintf(os.Stderr, "%s", prompt)
text, _ := reader.ReadString('\n')
return strings.TrimSpace(text)
}
// HashFile returns the hash of a file or, in case of a symlink, the
// SHA256 hash of its target. Takes an argument to specify the algorithm to use.
func HashFile(fname string, algorithm string, showProgress ...bool) (hash256 []byte, err error) {
doShowProgress := false
if len(showProgress) > 0 {
doShowProgress = showProgress[0]
}
var fstats os.FileInfo
fstats, err = os.Lstat(fname)
if err != nil {
return nil, err
}
if fstats.Mode()&os.ModeSymlink != 0 {
var target string
target, err = os.Readlink(fname)
if err != nil {
return nil, err
}
return []byte(SHA256(target)), nil
}
switch algorithm {
case "imohash":
return IMOHashFile(fname)
case "md5":
return MD5HashFile(fname, doShowProgress)
case "xxhash":
return XXHashFile(fname, doShowProgress)
case "highway":
return HighwayHashFile(fname, doShowProgress)
}
err = fmt.Errorf("unspecified algorithm")
return
}
// HighwayHashFile returns highwayhash of a file
func HighwayHashFile(fname string, doShowProgress bool) (hashHighway []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
}
defer f.Close()
key, err := hex.DecodeString("1553c5383fb0b86578c3310da665b4f6e0521acf22eb58a99532ffed02a6b115")
if err != nil {
return
}
h, err := highwayhash.New(key)
if err != nil {
err = fmt.Errorf("could not create highwayhash: %s", err.Error())
return
}
if doShowProgress {
stat, _ := f.Stat()
fnameShort := path.Base(fname)
if len(fnameShort) > 20 {
fnameShort = fnameShort[:20] + "..."
}
bar := progressbar.NewOptions64(stat.Size(),
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionShowBytes(true),
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
progressbar.OptionClearOnFinish(),
)
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
return
}
} else {
if _, err = io.Copy(h, f); err != nil {
return
}
}
hashHighway = h.Sum(nil)
return
}
// MD5HashFile returns MD5 hash
func MD5HashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
}
defer f.Close()
h := md5.New()
if doShowProgress {
stat, _ := f.Stat()
fnameShort := path.Base(fname)
if len(fnameShort) > 20 {
fnameShort = fnameShort[:20] + "..."
}
bar := progressbar.NewOptions64(stat.Size(),
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionShowBytes(true),
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
progressbar.OptionClearOnFinish(),
)
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
return
}
} else {
if _, err = io.Copy(h, f); err != nil {
return
}
}
hash256 = h.Sum(nil)
return
}
var imofull = imohash.NewCustom(0, 0)
var imopartial = imohash.NewCustom(16*16*8*1024, 128*1024)
// IMOHashFile returns imohash
func IMOHashFile(fname string) (hash []byte, err error) {
b, err := imopartial.SumFile(fname)
hash = b[:]
return
}
// IMOHashFileFull returns imohash of full file
func IMOHashFileFull(fname string) (hash []byte, err error) {
b, err := imofull.SumFile(fname)
hash = b[:]
return
}
// XXHashFile returns the xxhash of a file
func XXHashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
}
defer f.Close()
h := xxhash.New()
if doShowProgress {
stat, _ := f.Stat()
fnameShort := path.Base(fname)
if len(fnameShort) > 20 {
fnameShort = fnameShort[:20] + "..."
}
bar := progressbar.NewOptions64(stat.Size(),
progressbar.OptionSetWriter(os.Stderr),
progressbar.OptionShowBytes(true),
progressbar.OptionSetDescription(fmt.Sprintf("Hashing %s", fnameShort)),
progressbar.OptionClearOnFinish(),
)
if _, err = io.Copy(io.MultiWriter(h, bar), f); err != nil {
return
}
} else {
if _, err = io.Copy(h, f); err != nil {
return
}
}
hash256 = h.Sum(nil)
return
}
// SHA256 returns sha256 sum
func SHA256(s string) string {
sha := sha256.New()
sha.Write([]byte(s))
return hex.EncodeToString(sha.Sum(nil))
}
// PublicIP returns public ip address
func PublicIP() (ip string, err error) {
// 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()
// 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
}
// LocalIP returns local ip address
func LocalIP() string {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Error(err)
return ""
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP.String()
}
func GenerateRandomPin() string {
s := ""
max := new(big.Int)
max.SetInt64(9)
for i := 0; i < NbPinNumbers; i++ {
v, err := rand.Int(rand.Reader, max)
if err != nil {
panic(err)
}
s += fmt.Sprintf("%d", v)
}
return s
}
// GetRandomName returns mnemonicoded random name
func GetRandomName() string {
var result []string
bs := make([]byte, NbBytesWords)
rand.Read(bs)
result = mnemonicode.EncodeWordList(result, bs)
return GenerateRandomPin() + "-" + strings.Join(result, "-")
}
// ByteCountDecimal converts bytes to human readable byte string
func ByteCountDecimal(b int64) string {
const unit = 1024
if b < unit {
return fmt.Sprintf("%d B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%.1f %cB", float64(b)/float64(div), "kMGTPE"[exp])
}
// MissingChunks returns the positions of missing chunks.
// If file doesn't exist, it returns an empty chunk list (all chunks).
// If the file size is not the same as requested, it returns an empty chunk list (all chunks).
func MissingChunks(fname string, fsize int64, chunkSize int) (chunkRanges []int64) {
f, err := os.Open(fname)
if err != nil {
return
}
defer f.Close()
fstat, err := os.Stat(fname)
if err != nil || fstat.Size() != fsize {
return
}
emptyBuffer := make([]byte, chunkSize)
chunkNum := 0
chunks := make([]int64, int64(math.Ceil(float64(fsize)/float64(chunkSize))))
var currentLocation int64
for {
buffer := make([]byte, chunkSize)
bytesread, err := f.Read(buffer)
if err != nil {
break
}
if bytes.Equal(buffer[:bytesread], emptyBuffer[:bytesread]) {
chunks[chunkNum] = currentLocation
chunkNum++
}
currentLocation += int64(bytesread)
}
if chunkNum == 0 {
chunkRanges = []int64{}
} else {
chunks = chunks[:chunkNum]
chunkRanges = []int64{int64(chunkSize), chunks[0]}
curCount := 0
for i, chunk := range chunks {
if i == 0 {
continue
}
curCount++
if chunk-chunks[i-1] > int64(chunkSize) {
chunkRanges = append(chunkRanges, int64(curCount))
chunkRanges = append(chunkRanges, chunk)
curCount = 0
}
}
chunkRanges = append(chunkRanges, int64(curCount+1))
}
return
}
// ChunkRangesToChunks converts chunk ranges to list
func ChunkRangesToChunks(chunkRanges []int64) (chunks []int64) {
if len(chunkRanges) == 0 {
return
}
chunkSize := chunkRanges[0]
chunks = []int64{}
for i := 1; i < len(chunkRanges); i += 2 {
for j := int64(0); j < (chunkRanges[i+1]); j++ {
chunks = append(chunks, chunkRanges[i]+j*chunkSize)
}
}
return
}
// GetLocalIPs returns all local ips
func GetLocalIPs() (ips []string, err error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return
}
ips = []string{}
for _, address := range addrs {
// check the address type and if it is not a loopback the display it
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ips = append(ips, ipnet.IP.String())
}
}
}
return
}
func RandomFileName() (fname string, err error) {
f, err := os.CreateTemp(".", "croc-stdin-")
if err != nil {
return
}
fname = f.Name()
_ = f.Close()
return
}
func FindOpenPorts(host string, portNumStart, numPorts int) (openPorts []int) {
openPorts = []int{}
for port := portNumStart; port-portNumStart < 200; port++ {
timeout := 100 * time.Millisecond
conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, fmt.Sprint(port)), timeout)
if conn != nil {
conn.Close()
} else if err != nil {
openPorts = append(openPorts, port)
}
if len(openPorts) >= numPorts {
return
}
}
return
}
// local ip determination
// https://stackoverflow.com/questions/41240761/check-if-ip-address-is-in-private-network-space
var privateIPBlocks []*net.IPNet
func init() {
for _, cidr := range []string{
"127.0.0.0/8", // IPv4 loopback
"10.0.0.0/8", // RFC1918
"172.16.0.0/12", // RFC1918
"192.168.0.0/16", // RFC1918
"169.254.0.0/16", // RFC3927 link-local
"::1/128", // IPv6 loopback
"fe80::/10", // IPv6 link-local
"fc00::/7", // IPv6 unique local addr
} {
_, block, err := net.ParseCIDR(cidr)
if err != nil {
panic(fmt.Errorf("parse error on %q: %v", cidr, err))
}
privateIPBlocks = append(privateIPBlocks, block)
}
}
func IsLocalIP(ipaddress string) bool {
if strings.Contains(ipaddress, "127.0.0.1") {
return true
}
host, _, _ := net.SplitHostPort(ipaddress)
ip := net.ParseIP(host)
if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
return true
}
for _, block := range privateIPBlocks {
if block.Contains(ip) {
return true
}
}
return false
}
func ZipDirectory(destination string, source string) (err error) {
if _, err = os.Stat(destination); err == nil {
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.Error(err)
}
defer file.Close()
writer := zip.NewWriter(file)
// no compression because croc does its compression on the fly
writer.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(out, flate.NoCompression)
})
defer writer.Close()
err = filepath.Walk(source, func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Error(err)
}
if info.Mode().IsRegular() {
f1, err := os.Open(path)
if err != nil {
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.Error(err)
}
if _, err := io.Copy(w1, f1); err != nil {
log.Error(err)
}
fmt.Fprintf(os.Stderr, "\r\033[2K")
fmt.Fprintf(os.Stderr, "\rAdding %s", zipPath)
}
return nil
})
if err != nil {
log.Error(err)
}
fmt.Fprintf(os.Stderr, "\n")
return nil
}
func UnzipDirectory(destination string, source string) error {
archive, err := zip.OpenReader(source)
if err != nil {
log.Error(err)
}
defer archive.Close()
for _, f := range archive.File {
filePath := filepath.Join(destination, f.Name)
fmt.Fprintf(os.Stderr, "\r\033[2K")
fmt.Fprintf(os.Stderr, "\rUnzipping file %s", filePath)
// Issue #593 conceal path traversal vulnerability
// make sure the filepath does not have ".."
filePath = filepath.Clean(filePath)
if strings.Contains(filePath, "..") {
log.Errorf("Invalid file path %s\n", filePath)
}
if f.FileInfo().IsDir() {
os.MkdirAll(filePath, os.ModePerm)
continue
}
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
log.Error(err)
}
// check if file exists
if _, err := os.Stat(filePath); err == nil {
prompt := fmt.Sprintf("\nOverwrite '%s'? (y/N) ", filePath)
choice := strings.ToLower(GetInput(prompt))
if choice != "y" && choice != "yes" {
fmt.Fprintf(os.Stderr, "Skipping '%s'\n", filePath)
continue
}
}
dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
log.Error(err)
}
fileInArchive, err := f.Open()
if err != nil {
log.Error(err)
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
log.Error(err)
}
dstFile.Close()
fileInArchive.Close()
}
fmt.Fprintf(os.Stderr, "\n")
return nil
}
// 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 '%x'", string(r), r, fname)
return
}
if !unicode.IsPrint(r) {
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
}

267
src/utils/utils_test.go Normal file
View File

@ -0,0 +1,267 @@
package utils
import (
"bytes"
"fmt"
"log"
"math/rand"
"os"
"path"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
const TCP_BUFFER_SIZE = 1024 * 64
var bigFileSize = 75000000
func bigFile() {
os.WriteFile("bigfile.test", bytes.Repeat([]byte("z"), bigFileSize), 0o666)
}
func BenchmarkMD5(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
MD5HashFile("bigfile.test", false)
}
}
func BenchmarkXXHash(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
XXHashFile("bigfile.test", false)
}
}
func BenchmarkImoHash(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
IMOHashFile("bigfile.test")
}
}
func BenchmarkHighwayHash(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
HighwayHashFile("bigfile.test", false)
}
}
func BenchmarkImoHashFull(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
IMOHashFileFull("bigfile.test")
}
}
func BenchmarkSha256(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
SHA256("hello,world")
}
}
func BenchmarkMissingChunks(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
MissingChunks("bigfile.test", int64(bigFileSize), TCP_BUFFER_SIZE/2)
}
}
func TestExists(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
fmt.Println(GetLocalIPs())
assert.True(t, Exists("bigfile.test"))
assert.False(t, Exists("doesnotexist"))
}
func TestMD5HashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := MD5HashFile("bigfile.test", false)
assert.Nil(t, err)
assert.Equal(t, "8304ff018e02baad0e3555bade29a405", fmt.Sprintf("%x", b))
_, err = MD5HashFile("bigfile.test.nofile", false)
assert.NotNil(t, err)
}
func TestHighwayHashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := HighwayHashFile("bigfile.test", false)
assert.Nil(t, err)
assert.Equal(t, "3c32999529323ed66a67aeac5720c7bf1301dcc5dca87d8d46595e85ff990329", fmt.Sprintf("%x", b))
_, err = HighwayHashFile("bigfile.test.nofile", false)
assert.NotNil(t, err)
}
func TestIMOHashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := IMOHashFile("bigfile.test")
assert.Nil(t, err)
assert.Equal(t, "c0d1e12301e6c635f6d4a8ea5c897437", fmt.Sprintf("%x", b))
}
func TestXXHashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := XXHashFile("bigfile.test", false)
assert.Nil(t, err)
assert.Equal(t, "4918740eb5ccb6f7", fmt.Sprintf("%x", b))
_, err = XXHashFile("nofile", false)
assert.NotNil(t, err)
}
func TestSHA256(t *testing.T) {
assert.Equal(t, "09ca7e4eaa6e8ae9c7d261167129184883644d07dfba7cbfbc4c8a2e08360d5b", SHA256("hello, world"))
}
func TestByteCountDecimal(t *testing.T) {
assert.Equal(t, "10.0 kB", ByteCountDecimal(10240))
assert.Equal(t, "50 B", ByteCountDecimal(50))
assert.Equal(t, "12.4 MB", ByteCountDecimal(13002343))
}
func TestMissingChunks(t *testing.T) {
fileSize := 100
chunkSize := 10
rand.Seed(1)
bigBuff := make([]byte, fileSize)
rand.Read(bigBuff)
os.WriteFile("missing.test", bigBuff, 0o644)
empty := make([]byte, chunkSize)
f, err := os.OpenFile("missing.test", os.O_RDWR, 0o644)
assert.Nil(t, err)
for block := 0; block < fileSize/chunkSize; block++ {
if block == 0 || block == 4 || block == 5 || block >= 7 {
f.WriteAt(empty, int64(block*chunkSize))
}
}
f.Close()
chunkRanges := MissingChunks("missing.test", int64(fileSize), chunkSize)
assert.Equal(t, []int64{10, 0, 1, 40, 2, 70, 3}, chunkRanges)
chunks := ChunkRangesToChunks(chunkRanges)
assert.Equal(t, []int64{0, 40, 50, 70, 80, 90}, chunks)
os.Remove("missing.test")
content := []byte("temporary file's content")
tmpfile, err := os.CreateTemp("", "example")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpfile.Name()) // clean up
if _, err := tmpfile.Write(content); err != nil {
panic(err)
}
if err := tmpfile.Close(); err != nil {
panic(err)
}
chunkRanges = MissingChunks(tmpfile.Name(), int64(len(content)), chunkSize)
assert.Empty(t, chunkRanges)
chunkRanges = MissingChunks(tmpfile.Name(), int64(len(content)+10), chunkSize)
assert.Empty(t, chunkRanges)
chunkRanges = MissingChunks(tmpfile.Name()+"ok", int64(len(content)), chunkSize)
assert.Empty(t, chunkRanges)
chunks = ChunkRangesToChunks(chunkRanges)
assert.Empty(t, chunks)
}
// func Test1(t *testing.T) {
// chunkRanges := MissingChunks("../../m/bigfile.test", int64(75000000), 1024*64/2)
// fmt.Println(chunkRanges)
// fmt.Println(ChunkRangesToChunks((chunkRanges)))
// assert.Nil(t, nil)
// }
func TestHashFile(t *testing.T) {
content := []byte("temporary file's content")
tmpfile, err := os.CreateTemp("", "example")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpfile.Name()) // clean up
if _, err = tmpfile.Write(content); err != nil {
panic(err)
}
if err = tmpfile.Close(); err != nil {
panic(err)
}
hashed, err := HashFile(tmpfile.Name(), "xxhash")
assert.Nil(t, err)
assert.Equal(t, "e66c561610ad51e2", fmt.Sprintf("%x", hashed))
}
func TestPublicIP(t *testing.T) {
ip, err := PublicIP()
fmt.Println(ip)
assert.True(t, strings.Contains(ip, ".") || strings.Contains(ip, ":"))
assert.Nil(t, err)
}
func TestLocalIP(t *testing.T) {
ip := LocalIP()
fmt.Println(ip)
assert.True(t, strings.Contains(ip, ".") || strings.Contains(ip, ":"))
}
func TestGetRandomName(t *testing.T) {
name := GetRandomName()
fmt.Println(name)
assert.NotEmpty(t, name)
}
func intSliceSame(a, b []int) bool {
if len(a) != len(b) {
return false
}
for i, v := range a {
if v != b[i] {
return false
}
}
return true
}
func TestFindOpenPorts(t *testing.T) {
openPorts := FindOpenPorts("127.0.0.1", 9009, 4)
if !intSliceSame(openPorts, []int{9009, 9010, 9011, 9012}) && !intSliceSame(openPorts, []int{9014, 9015, 9016, 9017}) {
t.Errorf("openPorts: %v", openPorts)
}
}
func TestIsLocalIP(t *testing.T) {
assert.True(t, IsLocalIP("192.168.0.14:9009"))
}
func TestValidFileName(t *testing.T) {
// contains regular characters
assert.Nil(t, ValidFileName("中文.csl"))
// contains regular characters
assert.Nil(t, ValidFileName("[something].csl"))
// contains regular characters
assert.Nil(t, ValidFileName("[(something)].csl"))
// contains invisible character
err := ValidFileName("D中文.cslouglas")
assert.NotNil(t, err)
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")))
}

View File

@ -1,196 +0,0 @@
package zipper
import (
"archive/zip"
"compress/flate"
"io"
"os"
"path"
"path/filepath"
"strings"
log "github.com/cihub/seelog"
"github.com/schollz/croc/src/logger"
)
var DebugLevel string
func init() {
DebugLevel = "info"
}
// UnzipFile will unzip the src directory into the dest
func UnzipFile(src, dest string) (err error) {
logger.SetLogLevel(DebugLevel)
r, err := zip.OpenReader(src)
if err != nil {
return
}
defer r.Close()
for _, f := range r.File {
var rc io.ReadCloser
rc, err = f.Open()
if err != nil {
return
}
defer rc.Close()
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
log.Debugf("unzipping %s", fpath)
fpath = filepath.FromSlash(fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
} else {
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return
}
var outFile *os.File
outFile, err = os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
if err != nil {
return
}
}
}
if err == nil {
log.Debugf("unzipped %s to %s", src, dest)
}
return
}
// ZipFile will zip the folder
func ZipFile(fname string, compress bool) (writtenFilename string, err error) {
logger.SetLogLevel(DebugLevel)
log.Debugf("zipping %s with compression? %v", fname, compress)
// get absolute filename
fname, err = filepath.Abs(fname)
if err != nil {
log.Error(err)
return
}
// get path to file and the filename
fpath, fname := filepath.Split(fname)
writtenFilename = fname + ".croc.zip"
log.Debugf("creating file: %s", writtenFilename)
f, err := os.Create(writtenFilename)
if err != nil {
log.Error(err)
return
}
zipWriter := zip.NewWriter(f)
zipWriter.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
if compress {
return flate.NewWriter(out, flate.BestSpeed)
} else {
return flate.NewWriter(out, flate.NoCompression)
}
})
defer zipWriter.Close()
// Get the file information for the target
log.Debugf("checking %s", path.Join(fpath, fname))
ftarget, err := os.Open(path.Join(fpath, fname))
if err != nil {
log.Error(err)
return
}
defer ftarget.Close()
info, err := ftarget.Stat()
if err != nil {
log.Error(err)
return
}
// write header informaiton
header, err := zip.FileInfoHeader(info)
if err != nil {
log.Error(err)
return
}
var writer io.Writer
if info.IsDir() {
baseDir := path.Join(fpath, fname)
log.Debugf("walking base dir: %s", baseDir)
filepath.Walk(baseDir, func(curpath string, info os.FileInfo, err error) error {
if err != nil {
log.Error(err)
return err
}
header, err := zip.FileInfoHeader(info)
if err != nil {
log.Error(err)
return err
}
if baseDir != "" {
header.Name = path.Join(fname, strings.TrimPrefix(curpath, baseDir))
}
log.Debug(header.Name)
if info.IsDir() {
header.Name += "/"
} else {
header.Method = zip.Deflate
}
header.Name = filepath.ToSlash(header.Name)
writer, err = zipWriter.CreateHeader(header)
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(curpath)
if err != nil {
log.Error(err)
return err
}
defer file.Close()
_, err = io.Copy(writer, file)
return err
})
} else {
writer, err = zipWriter.CreateHeader(header)
if err != nil {
log.Error(err)
return
}
_, err = io.Copy(writer, ftarget)
if err != nil {
log.Error(err)
return
}
}
log.Debugf("wrote zip file to %s", writtenFilename)
return
}

View File

@ -1,29 +0,0 @@
package zipper
import (
"os"
"testing"
log "github.com/cihub/seelog"
"github.com/schollz/croc/src/utils"
"github.com/stretchr/testify/assert"
)
func TestZip(t *testing.T) {
defer log.Flush()
DebugLevel = "debug"
writtenFilename, err := ZipFile("../croc", true)
assert.Nil(t, err)
defer os.Remove(writtenFilename)
err = UnzipFile(writtenFilename, ".")
assert.Nil(t, err)
assert.True(t, utils.Exists("croc"))
writtenFilename, err = ZipFile("../../README.md", false)
assert.Nil(t, err)
defer os.Remove(writtenFilename)
err = UnzipFile(writtenFilename, ".")
assert.Nil(t, err)
assert.True(t, utils.Exists("README.md"))
}