Compare commits

...

259 Commits
v9.5.5 ... main

Author SHA1 Message Date
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
34 changed files with 1468 additions and 415 deletions

View File

@ -2,7 +2,6 @@
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
@ -12,15 +11,10 @@ assignees: ''
<!-- Please try to download latest, https://github.com/schollz/croc/releases/latest of croc before reporting a bug! -->
## Describe the bug
<-- A clear and concise description of what the bug is. -->
## To Reproduce
Steps to reproduce the behavior:
<-- 1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error -->
1.
2.
@ -28,14 +22,10 @@ Steps to reproduce the behavior:
4.
## Expected behaviour
<-- A clear and concise description of what you expected to happen. -->
## Version
<-- Check "croc -v" and report it -->
## Additional context
<-- Add any other context about the problem here. -->

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"

View File

@ -1,18 +1,18 @@
name: CI
on:
push:
branches: [master]
branches: [main]
pull_request:
branches: [master]
branches: [main]
jobs:
unit-tests:
name: Go unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.18'
go-version: '1.20'
- run: go version
- run: go test -v ./...

View File

@ -4,10 +4,15 @@ name: CD
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the master branch
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ master ]
branches:
- '*'
tags:
- 'v*'
pull_request:
branches:
- '*'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
@ -19,32 +24,37 @@ jobs:
steps:
-
name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
-
name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
uses: docker/metadata-action@v5
with:
images: schollz/croc
# tag-semver: "{{version}}"
tag-sha: true
tag-latest: true
# 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@v1
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile

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

@ -0,0 +1,123 @@
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.20'
- name: Build Windows 7
run: |
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-64bit.zip croc.exe
CGO_ENABLED=0 GOOS=windows GOARCH=386 go build -ldflags '-extldflags "-static"' -o croc.exe
zip croc_${{ github.event.release.name }}_Windows7-32bit.zip croc.exe
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'
- 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
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: 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-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-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 }}

2
.gitignore vendored
View File

@ -9,3 +9,5 @@ croc-stdin*
.idea/
.vscode/
src/utils/bigfile.test
test1/

View File

@ -97,4 +97,4 @@ announce:
twitter:
# Wether its enabled or not.
# Defaults to false.
enabled: true
enabled: false

View File

@ -10,12 +10,12 @@ install: true
script:
- env GO111MODULE=on go build -v
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/compress
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/croc
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/crypt
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/tcp
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/utils
- env GO111MODULE=on go test -v -cover github.com/schollz/croc/v9/src/comm
- 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:

View File

@ -1,5 +1,5 @@
FROM golang:1.17-alpine as builder
RUN apk add --no-cache git
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"

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-2021 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

View File

@ -4,10 +4,9 @@
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-v9.5.5-brightgreen.svg?style=flat-square" alt="Version"></a>
<a href="https://coveralls.io/github/schollz/croc"><img src="https://img.shields.io/badge/coverage-81%25-green.svg?style=flat-square" alt="Coverage"></a>
<a href="https://travis-ci.org/schollz/croc"><img
src="https://img.shields.io/travis/schollz/croc.svg?style=flat-square" alt="Build
<a href="https://github.com/schollz/croc/releases/latest"><img src="https://img.shields.io/badge/version-v10.0.7-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>
@ -48,7 +47,7 @@ sudo port selfupdate
sudo port install croc
```
On Windows you can install the latest release with [Scoop](https://scoop.sh/) or [Chocolatey](https://chocolatey.org):
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
@ -58,6 +57,10 @@ scoop install croc
choco install croc
```
```
winget install schollz.croc
```
On Unix you can install the latest release with [Nix](https://nixos.org/nix):
```
@ -78,6 +81,12 @@ 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
@ -98,7 +107,7 @@ pkg install croc
Or, you can [install Go](https://golang.org/dl/) and build from source (requires Go 1.17+):
```
go install github.com/schollz/croc/v9@latest
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/).
@ -203,7 +212,7 @@ The relay is needed to staple the parallel incoming and outgoing connections. By
croc relay
```
By default it uses TCP ports 9009-9013. Make sure to open those up. You can customized 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.
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.
@ -236,6 +245,6 @@ 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, ask a question, or tweet me ([@yakczar](http://ctt.ec/Rq054)).
`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)!

View File

@ -4,7 +4,7 @@ After=network.target
[Service]
Type=simple
User=nobody
DynamicUser=yes
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
ExecStart=/usr/bin/croc relay

49
go.mod
View File

@ -1,39 +1,42 @@
module github.com/schollz/croc/v9
module github.com/schollz/croc/v10
go 1.17
go 1.20
require (
github.com/cespare/xxhash v1.1.0
github.com/chzyer/readline v1.5.1
github.com/denisbrodbeck/machineid v1.0.1
github.com/kalafut/imohash v1.0.2
github.com/kalafut/imohash v1.0.3
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
github.com/schollz/cli/v2 v2.2.1
github.com/schollz/logger v1.2.0
github.com/schollz/mnemonicode v1.0.1
github.com/schollz/pake/v3 v3.0.4
github.com/schollz/peerdiscovery v1.6.11
github.com/schollz/progressbar/v3 v3.8.6
github.com/stretchr/testify v1.6.1
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
golang.org/x/time v0.0.0-20220411224347-583f2d630306
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d
github.com/schollz/pake/v3 v3.0.5
github.com/schollz/peerdiscovery v1.7.3
github.com/schollz/progressbar/v3 v3.14.3
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.23.0
golang.org/x/net v0.25.0
golang.org/x/time v0.5.0
)
require github.com/minio/highwayhash v1.0.2
require (
github.com/OneOfOne/xxhash v1.2.5 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tscholl2/siec v0.0.0-20210707234609-9bdfc483d499 // indirect
github.com/twmb/murmur3 v1.1.6 // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
github.com/tscholl2/siec v0.0.0-20240310163802-c2c6f6198406 // indirect
github.com/twmb/murmur3 v1.1.8 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

137
go.sum
View File

@ -1,93 +1,132 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ=
github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kalafut/imohash v1.0.2 h1:j/cUPa15YvXv7abJlM+kdJIycbBMpmO7WqhPl4YB76I=
github.com/kalafut/imohash v1.0.2/go.mod h1:PjHBF0vpo1q7zMqiTn0qwSTQU2wDn5QIe8S8sFQuZS8=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kalafut/imohash v1.0.3 h1:p9c61km8+6ZMqKRnERwdoxp/CztrdLNEbpsyGgf+A4M=
github.com/kalafut/imohash v1.0.3/go.mod h1:6cn9lU0Sj8M4eu9UaQm1kR/5y3k/ayB68yntRhGloL4=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b h1:xZ59n7Frzh8CwyfAapUZLSg+gXH5m63YEaFCMpDHhpI=
github.com/magisterquis/connectproxy v0.0.0-20200725203833-3582e84f0c9b/go.mod h1:uDd4sYVYsqcxAB8j+Q7uhL6IJCs/r1kxib1HV4bgOMg=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
github.com/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.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
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/mnemonicode v1.0.1 h1:LiH5hwADZwjwnfXsaD4xgnMyTAtaKHN+e5AyjRU6WSU=
github.com/schollz/mnemonicode v1.0.1/go.mod h1:cl4UAOhUV0mkdjMj/QYaUZbZZdF8BnOqoz8rHMzwboY=
github.com/schollz/pake/v3 v3.0.4 h1:rDNk9MwEVJ/C1+eDCr0DirJfpG+/sAZJ4YsYIyOTkSc=
github.com/schollz/pake/v3 v3.0.4/go.mod h1:Q28rSQCHYzEtMQoi80R1MdpPRgNN/Si2Xdilx4NvsoQ=
github.com/schollz/peerdiscovery v1.6.11 h1:3SG5vV1plIxylDg81fKgnqyrvlem5MrNcgcb0TLBjlE=
github.com/schollz/peerdiscovery v1.6.11/go.mod h1:duO2S6wH3IuPJXwniPXp/9f69S2gFUSA9ePbAcKatJg=
github.com/schollz/progressbar/v3 v3.8.6 h1:QruMUdzZ1TbEP++S1m73OqRJk20ON11m6Wqv4EoGg8c=
github.com/schollz/progressbar/v3 v3.8.6/go.mod h1:W5IEwbJecncFGBvuEh4A7HT1nZZ6WNIL2i3qbnI0WKY=
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d h1:3zCjdgCJbo9Fot3UoqZkpGiDgT6Nf+iUnOsDEJQay+c=
github.com/schollz/mnemonicode v1.0.2-0.20190421205639-63fa713ece0d/go.mod h1:cl4UAOhUV0mkdjMj/QYaUZbZZdF8BnOqoz8rHMzwboY=
github.com/schollz/pake/v3 v3.0.5 h1:MnZVdI987lkjln9BSx/zUb724TZISa2jbO+dPj6BvgQ=
github.com/schollz/pake/v3 v3.0.5/go.mod h1:OGbG6htRwSKo6V8R5tg61ufpFmZM1b/PrrSp6g2ZLLc=
github.com/schollz/peerdiscovery v1.7.3 h1:/pt1G0rZ80fSPoI/FgGC5P7MxpkRXD6u0pe6PJbYcIE=
github.com/schollz/peerdiscovery v1.7.3/go.mod h1:mVlPNJ5DWbMi52VzpXxGbqXKdFANx3qw0Jsp3EQMCrE=
github.com/schollz/progressbar/v3 v3.14.3 h1:oOuWW19ka12wxYU1XblR4n16wF/2Y1dBLMarMo6p4xU=
github.com/schollz/progressbar/v3 v3.14.3/go.mod h1:aT3UQ7yGm+2ZjeXPqsjTenwL3ddUiuZ0kfQ/2tHlyNI=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tscholl2/siec v0.0.0-20210707234609-9bdfc483d499 h1:bPQ48TuiAuGTZDm54H2EV/2+eRRBHP61bKDkKSEPW4A=
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.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
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.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
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/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.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/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-20210423082822-04245dca01da/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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.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 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/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.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
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/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tylerb/is.v1 v1.1.2 h1:AB/MANFml2ySf+adwcinvajyHvsYltAOD+rb/8njfSU=
gopkg.in/tylerb/is.v1 v1.1.2/go.mod h1:9yQB2tyIhZ5oph6Kk5Sq7cJMd9c5Jpa1p3hr9kxzPqo=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
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

@ -7,7 +7,7 @@ package main
import (
"log"
"github.com/schollz/croc/v9/src/cli"
"github.com/schollz/croc/v10/src/cli"
)
func main() {

View File

@ -9,16 +9,19 @@ import (
"path"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/chzyer/readline"
"github.com/schollz/cli/v2"
"github.com/schollz/croc/v9/src/comm"
"github.com/schollz/croc/v9/src/croc"
"github.com/schollz/croc/v9/src/models"
"github.com/schollz/croc/v9/src/tcp"
"github.com/schollz/croc/v9/src/utils"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/croc"
"github.com/schollz/croc/v10/src/models"
"github.com/schollz/croc/v10/src/tcp"
"github.com/schollz/croc/v10/src/utils"
log "github.com/schollz/logger"
"github.com/schollz/mnemonicode"
"github.com/schollz/pake/v3"
)
@ -33,7 +36,7 @@ func Run() (err error) {
app := cli.NewApp()
app.Name = "croc"
if Version == "" {
Version = "v9.5.5-a6a3a57"
Version = "v10.0.7"
}
app.Version = Version
app.Compiled = time.Now()
@ -41,6 +44,7 @@ func Run() (err error) {
app.UsageText = `Send a file:
croc send file.txt
-git to respect your .gitignore
Send multiple files:
croc send file1.txt file2.txt file3.txt
or
@ -61,12 +65,15 @@ func Run() (err error) {
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.StringFlag{Name: "ports", Value: "9009,9010,9011,9012,9013", Usage: "ports of the local relay (optional)"},
&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"},
},
HelpName: "croc send",
Action: send,
@ -85,6 +92,7 @@ func Run() (err error) {
}
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"},
@ -94,6 +102,7 @@ func Run() (err error) {
&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"},
&cli.BoolFlag{Name: "testing", Usage: "flag for testing purposes"},
&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"}},
@ -101,6 +110,7 @@ func Run() (err error) {
&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
@ -116,6 +126,61 @@ func Run() (err error) {
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{}
@ -129,6 +194,7 @@ func Run() (err error) {
return send(c)
}
}
return receive(c)
}
@ -144,8 +210,8 @@ func setDebugLevel(c *cli.Context) {
}
}
func getConfigFile() string {
configFile, err := utils.GetConfigDir()
func getSendConfigFile(requireValidPath bool) string {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
log.Error(err)
return ""
@ -153,6 +219,24 @@ func getConfigFile() string {
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)
@ -165,6 +249,22 @@ func determinePass(c *cli.Context) (pass string) {
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,
@ -176,7 +276,7 @@ func send(c *cli.Context) (err error) {
DisableLocal: c.Bool("no-local"),
OnlyLocal: c.Bool("local"),
IgnoreStdin: c.Bool("ignore-stdin"),
RelayPorts: strings.Split(c.String("ports"), ","),
RelayPorts: ports,
Ask: c.Bool("ask"),
NoMultiplexing: c.Bool("no-multi"),
RelayPassword: determinePass(c),
@ -186,13 +286,15 @@ func send(c *cli.Context) (err error) {
Curve: c.String("curve"),
HashAlgorithm: c.String("hash"),
ThrottleUpload: c.String("throttleUpload"),
ZipFolder: c.Bool("zip"),
GitIgnore: c.Bool("git"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
} else if crocOptions.RelayAddress6 != models.DEFAULT_RELAY6 {
crocOptions.RelayAddress = ""
}
b, errOpen := os.ReadFile(getConfigFile())
b, errOpen := os.ReadFile(getSendConfigFile(false))
if errOpen == nil && !c.Bool("remember") {
var rememberedOptions croc.Options
err = json.Unmarshal(b, &rememberedOptions)
@ -228,6 +330,12 @@ func send(c *cli.Context) (err error) {
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
@ -262,12 +370,37 @@ func send(c *cli.Context) (err error) {
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:
export CROC_SECRET="****"
croc send file.txt
Or you can have the code phrase automaticlaly 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)
minimalFileInfos, emptyFoldersToTransfer, totalNumberFolders, err := croc.GetFilesInfo(fnames, crocOptions.ZipFolder, crocOptions.GitIgnore)
if err != nil {
return
}
@ -323,7 +456,7 @@ func makeTempFileWithString(s string) (fnames []string, err error) {
func saveConfig(c *cli.Context, crocOptions croc.Options) {
if c.Bool("remember") {
configFile := getConfigFile()
configFile := getSendConfigFile(true)
log.Debug("saving config file")
var bConfig []byte
// if the code wasn't set, don't save it
@ -335,7 +468,7 @@ func saveConfig(c *cli.Context, crocOptions croc.Options) {
log.Error(err)
return
}
err = os.WriteFile(configFile, bConfig, 0644)
err = os.WriteFile(configFile, bConfig, 0o644)
if err != nil {
log.Error(err)
return
@ -344,8 +477,39 @@ func saveConfig(c *cli.Context, crocOptions croc.Options) {
}
}
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,
@ -360,6 +524,7 @@ func receive(c *cli.Context) (err error) {
IP: c.String("ip"),
Overwrite: c.Bool("overwrite"),
Curve: c.String("curve"),
TestFlag: c.Bool("testing"),
}
if crocOptions.RelayAddress != models.DEFAULT_RELAY {
crocOptions.RelayAddress6 = ""
@ -371,6 +536,8 @@ func receive(c *cli.Context) (err error) {
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()...)
@ -379,14 +546,14 @@ func receive(c *cli.Context) (err error) {
// load options here
setDebugLevel(c)
configFile, err := utils.GetConfigDir()
if err != nil {
log.Error(err)
doRemember := c.Bool("remember")
configFile, err := getReceiveConfigFile(doRemember)
if err != nil && doRemember {
return
}
configFile = path.Join(configFile, "receive.json")
b, errOpen := os.ReadFile(configFile)
if errOpen == nil && !c.Bool("remember") {
if errOpen == nil && !doRemember {
var rememberedOptions croc.Options
err = json.Unmarshal(b, &rememberedOptions)
if err != nil {
@ -420,8 +587,44 @@ func receive(c *cli.Context) (err error) {
}
}
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:
export 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 == "" {
crocOptions.SharedSecret = utils.GetInput("Enter receive code: ")
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 {
@ -435,7 +638,7 @@ func receive(c *cli.Context) (err error) {
}
// save the config
if c.Bool("remember") {
if doRemember {
log.Debug("saving config file")
var bConfig []byte
bConfig, err = json.MarshalIndent(crocOptions, "", " ")
@ -443,7 +646,7 @@ func receive(c *cli.Context) (err error) {
log.Error(err)
return
}
err = os.WriteFile(configFile, bConfig, 0644)
err = os.WriteFile(configFile, bConfig, 0o644)
if err != nil {
log.Error(err)
return
@ -469,7 +672,7 @@ func relay(c *cli.Context) (err error) {
continue
}
go func(portStr string) {
err = tcp.Run(debugString, host, portStr, determinePass(c))
err := tcp.Run(debugString, host, portStr, determinePass(c))
if err != nil {
panic(err)
}

View File

@ -10,12 +10,14 @@ import (
"strings"
"time"
"github.com/schollz/croc/v9/src/utils"
"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")
@ -39,7 +41,7 @@ func NewConnection(address string, timelimit ...time.Duration) (c *Comm, err err
}
socks5ProxyURL, urlParseError := url.Parse(Socks5Proxy)
if urlParseError != nil {
err = fmt.Errorf("Unable to parse socks proxy url: %s", urlParseError)
err = fmt.Errorf("unable to parse socks proxy url: %s", urlParseError)
log.Debug(err)
return
}
@ -51,6 +53,27 @@ func NewConnection(address string, timelimit ...time.Duration) (c *Comm, err err
}
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)
@ -115,7 +138,7 @@ func (c *Comm) Write(b []byte) (n int, err error) {
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 {
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
@ -152,7 +175,7 @@ func (c *Comm) Read() (buf []byte, numBytes int, bs []byte, err error) {
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 {
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)

View File

@ -31,7 +31,7 @@ func TestComm(t *testing.T) {
log.Error(err)
}
log.Debugf("client %s connected", connection.RemoteAddr().String())
go func(port string, connection net.Conn) {
go func(_ string, connection net.Conn) {
c := New(connection)
err = c.Send([]byte("hello, world"))
assert.Nil(t, err)
@ -49,7 +49,7 @@ func TestComm(t *testing.T) {
}()
time.Sleep(300 * time.Millisecond)
a, err := NewConnection("localhost:"+port, 10*time.Minute)
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)
@ -63,5 +63,4 @@ func TestComm(t *testing.T) {
assert.NotNil(t, a.Send(token))
_, err = a.Write(token)
assert.NotNil(t, err)
}

View File

@ -3,7 +3,9 @@ package croc
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"io"
@ -20,18 +22,19 @@ import (
"golang.org/x/time/rate"
"github.com/denisbrodbeck/machineid"
ignore "github.com/sabhiram/go-gitignore"
log "github.com/schollz/logger"
"github.com/schollz/pake/v3"
"github.com/schollz/peerdiscovery"
"github.com/schollz/progressbar/v3"
"github.com/schollz/croc/v9/src/comm"
"github.com/schollz/croc/v9/src/compress"
"github.com/schollz/croc/v9/src/crypt"
"github.com/schollz/croc/v9/src/message"
"github.com/schollz/croc/v9/src/models"
"github.com/schollz/croc/v9/src/tcp"
"github.com/schollz/croc/v9/src/utils"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/compress"
"github.com/schollz/croc/v10/src/crypt"
"github.com/schollz/croc/v10/src/message"
"github.com/schollz/croc/v10/src/models"
"github.com/schollz/croc/v10/src/tcp"
"github.com/schollz/croc/v10/src/utils"
)
var (
@ -56,6 +59,7 @@ func Debug(debug bool) {
type Options struct {
IsSender bool
SharedSecret string
RoomName string
Debug bool
RelayAddress string
RelayAddress6 string
@ -75,6 +79,14 @@ type Options struct {
Curve string
HashAlgorithm string
ThrottleUpload string
ZipFolder bool
TestFlag bool
GitIgnore bool
}
type SimpleMessage struct {
Bytes []byte
Kind string
}
// Client holds the state of the croc transfer
@ -99,6 +111,7 @@ type Client struct {
TotalNumberFolders int
FilesToTransferCurrentNum int
FilesHasFinished map[int]struct{}
TotalFilesIgnored int
// send / receive information of current file
CurrentFile *os.File
@ -146,6 +159,8 @@ type FileInfo struct {
IsEncrypted bool `json:"e,omitempty"`
Symlink string `json:"sy,omitempty"`
Mode os.FileMode `json:"md,omitempty"`
TempFile bool `json:"tf,omitempty"`
IsIgnored bool `json:"ig,omitempty"`
}
// RemoteFileRequest requests specific bytes
@ -175,19 +190,23 @@ func New(ops Options) (c *Client, err error) {
// setup basic info
c.Options = ops
Debug(c.Options.Debug)
log.Debugf("options: %+v", c.Options)
if len(c.Options.SharedSecret) < 6 {
err = fmt.Errorf("code is too short")
return
}
// Create a hash of part of the shared secret to use as the room name
hashExtra := "croc"
roomNameBytes := sha256.Sum256([]byte(c.Options.SharedSecret[:4] + hashExtra))
c.Options.RoomName = hex.EncodeToString(roomNameBytes[:])
c.conn = make([]*comm.Comm, 16)
// initialize throttler
if len(c.Options.ThrottleUpload) > 1 && c.Options.IsSender {
upload := c.Options.ThrottleUpload[:len(c.Options.ThrottleUpload)-1]
uploadLimit, err := strconv.ParseInt(upload, 10, 64)
var uploadLimit int64
uploadLimit, err = strconv.ParseInt(upload, 10, 64)
if err != nil {
panic("Could not parse given Upload Limit")
}
@ -206,7 +225,7 @@ func New(ops Options) (c *Client, err error) {
panic("Could not parse given Upload Limit")
}
}
// Somehow 4* is neccessary
// Somehow 4* is necessary
rt = rate.Every(time.Second / (4 * time.Duration(uploadLimit)))
if int(uploadLimit) > minBurstSize {
minBurstSize = int(uploadLimit)
@ -247,10 +266,52 @@ func isEmptyFolder(folderPath string) (bool, error) {
return false, nil
}
// This function retrives the important file informations
// for every file that will be transfered
func GetFilesInfo(fnames []string) (filesInfo []FileInfo, emptyFolders []FileInfo, totalNumberFolders int, err error) {
// fnames: the relativ/absolute paths of files/folders that will be transfered
// helper function to walk each subfolder and parses against an ignore file.
// returns a hashmap Key: Absolute filepath, Value: boolean (true=ignore)
func gitWalk(dir string, gitObj *ignore.GitIgnore, files map[string]bool) {
var ignoredDir bool
var current string
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if isChild(current, path) && ignoredDir {
files[path] = true
return nil
}
if info.IsDir() && filepath.Base(path) == filepath.Base(dir) {
ignoredDir = false // Skip applying ignore rules for root directory
return nil
}
if gitObj.MatchesPath(info.Name()) {
files[path] = true
ignoredDir = true
current = path
return nil
} else {
files[path] = false
ignoredDir = false
return nil
}
})
if err != nil {
log.Errorf("filepath error")
}
}
func isChild(parentPath, childPath string) bool {
relPath, err := filepath.Rel(parentPath, childPath)
if err != nil {
return false
}
return !strings.HasPrefix(relPath, "..")
}
// This function retrieves the important file information
// for every file that will be transferred
func GetFilesInfo(fnames []string, zipfolder bool, ignoreGit bool) (filesInfo []FileInfo, emptyFolders []FileInfo, totalNumberFolders int, err error) {
// fnames: the relative/absolute paths of files/folders that will be transferred
totalNumberFolders = 0
var paths []string
for _, fname := range fnames {
@ -267,21 +328,92 @@ func GetFilesInfo(fnames []string) (filesInfo []FileInfo, emptyFolders []FileInf
paths = append(paths, fname)
}
}
for _, path := range paths {
stat, errStat := os.Lstat(path)
var ignoredPaths = make(map[string]bool)
if ignoreGit {
wd, wdErr := os.Stat(".gitignore")
if wdErr == nil {
gitIgnore, gitErr := ignore.CompileIgnoreFile(wd.Name())
if gitErr == nil {
for _, path := range paths {
abs, absErr := filepath.Abs(path)
if absErr != nil {
err = absErr
return
}
if gitIgnore.MatchesPath(path) {
ignoredPaths[abs] = true
}
}
}
}
for _, path := range paths {
abs, absErr := filepath.Abs(path)
if absErr != nil {
err = absErr
return
}
file, fileErr := os.Stat(path)
if fileErr == nil && file.IsDir() {
_, subErr := os.Stat(filepath.Join(path, ".gitignore"))
if subErr == nil {
gitObj, gitObjErr := ignore.CompileIgnoreFile(filepath.Join(path, ".gitignore"))
if gitObjErr != nil {
err = gitObjErr
return
}
gitWalk(abs, gitObj, ignoredPaths)
}
}
}
}
for _, fpath := range paths {
stat, errStat := os.Lstat(fpath)
if errStat != nil {
err = errStat
return
}
absPath, errAbs := filepath.Abs(path)
absPath, errAbs := filepath.Abs(fpath)
if errAbs != nil {
err = errAbs
return
}
if stat.IsDir() && zipfolder {
if fpath[len(fpath)-1:] != "/" {
fpath += "/"
}
fpath = filepath.Dir(fpath)
dest := filepath.Base(fpath) + ".zip"
utils.ZipDirectory(dest, fpath)
stat, errStat = os.Lstat(dest)
if errStat != nil {
err = errStat
return
}
absPath, errAbs = filepath.Abs(dest)
if errAbs != nil {
err = errAbs
return
}
fInfo := FileInfo{
Name: stat.Name(),
FolderRemote: "./",
FolderSource: filepath.Dir(absPath),
Size: stat.Size(),
ModTime: stat.ModTime(),
Mode: stat.Mode(),
TempFile: true,
IsIgnored: ignoredPaths[absPath],
}
if fInfo.IsIgnored {
continue
}
filesInfo = append(filesInfo, fInfo)
continue
}
if stat.IsDir() {
err = filepath.Walk(absPath,
@ -292,22 +424,32 @@ func GetFilesInfo(fnames []string) (filesInfo []FileInfo, emptyFolders []FileInf
remoteFolder := strings.TrimPrefix(filepath.Dir(pathName),
filepath.Dir(absPath)+string(os.PathSeparator))
if !info.IsDir() {
filesInfo = append(filesInfo, FileInfo{
fInfo := FileInfo{
Name: info.Name(),
FolderRemote: strings.Replace(remoteFolder, string(os.PathSeparator), "/", -1) + "/",
FolderRemote: strings.ReplaceAll(remoteFolder, string(os.PathSeparator), "/") + "/",
FolderSource: filepath.Dir(pathName),
Size: info.Size(),
ModTime: info.ModTime(),
Mode: info.Mode(),
})
TempFile: false,
IsIgnored: ignoredPaths[pathName],
}
if fInfo.IsIgnored && ignoreGit {
return nil
} else {
filesInfo = append(filesInfo, fInfo)
}
} else {
totalNumberFolders++
if ignoredPaths[pathName] {
return filepath.SkipDir
}
isEmptyFolder, _ := isEmptyFolder(pathName)
totalNumberFolders++
if isEmptyFolder {
emptyFolders = append(emptyFolders, FileInfo{
// Name: info.Name(),
FolderRemote: strings.Replace(strings.TrimPrefix(pathName,
filepath.Dir(absPath)+string(os.PathSeparator)), string(os.PathSeparator), "/", -1) + "/",
FolderRemote: strings.ReplaceAll(strings.TrimPrefix(pathName,
filepath.Dir(absPath)+string(os.PathSeparator)), string(os.PathSeparator), "/") + "/",
})
}
}
@ -316,17 +458,24 @@ func GetFilesInfo(fnames []string) (filesInfo []FileInfo, emptyFolders []FileInf
if err != nil {
return
}
} else {
filesInfo = append(filesInfo, FileInfo{
fInfo := FileInfo{
Name: stat.Name(),
FolderRemote: "./",
FolderSource: filepath.Dir(absPath),
Size: stat.Size(),
ModTime: stat.ModTime(),
Mode: stat.Mode(),
})
TempFile: false,
IsIgnored: ignoredPaths[absPath],
}
if fInfo.IsIgnored && ignoreGit {
continue
} else {
filesInfo = append(filesInfo, fInfo)
}
}
}
return
}
@ -357,7 +506,7 @@ func (c *Client) sendCollectFiles(filesInfo []FileInfo) (err error) {
c.Options.HashAlgorithm = "xxhash"
}
c.FilesToTransfer[i].Hash, err = utils.HashFile(fullPath, c.Options.HashAlgorithm)
c.FilesToTransfer[i].Hash, err = utils.HashFile(fullPath, c.Options.HashAlgorithm, fileInfo.Size > 1e7)
log.Debugf("hashed %s to %x using %s", fullPath, c.FilesToTransfer[i].Hash, c.Options.HashAlgorithm)
totalFilesSize += fileInfo.Size
if err != nil {
@ -381,14 +530,18 @@ func (c *Client) sendCollectFiles(filesInfo []FileInfo) (err error) {
}
fmt.Fprintf(os.Stderr, "\r ")
fmt.Fprintf(os.Stderr, "\rSending %s and %s (%s)\n", fname, folderName, utils.ByteCountDecimal(totalFilesSize))
if c.TotalNumberFolders > 0 {
fmt.Fprintf(os.Stderr, "\rSending %s and %s (%s)\n", fname, folderName, utils.ByteCountDecimal(totalFilesSize))
} else {
fmt.Fprintf(os.Stderr, "\rSending %s (%s)\n", fname, utils.ByteCountDecimal(totalFilesSize))
}
return
}
func (c *Client) setupLocalRelay() {
// setup the relay locally
firstPort, _ := strconv.Atoi(c.Options.RelayPorts[0])
openPorts := utils.FindOpenPorts("localhost", firstPort, len(c.Options.RelayPorts))
openPorts := utils.FindOpenPorts("127.0.0.1", firstPort, len(c.Options.RelayPorts))
if len(openPorts) < len(c.Options.RelayPorts) {
panic("not enough open ports to run local relay")
}
@ -401,7 +554,7 @@ func (c *Client) setupLocalRelay() {
if c.Options.Debug {
debugString = "debug"
}
err := tcp.Run(debugString, "localhost", portStr, c.Options.RelayPassword, strings.Join(c.Options.RelayPorts[1:], ","))
err := tcp.Run(debugString, "127.0.0.1", portStr, c.Options.RelayPassword, strings.Join(c.Options.RelayPorts[1:], ","))
if err != nil {
panic(err)
}
@ -411,7 +564,7 @@ func (c *Client) setupLocalRelay() {
func (c *Client) broadcastOnLocalNetwork(useipv6 bool) {
var timeLimit time.Duration
//if we don't use an external relay, the broadcast messages need to be sent continuously
// if we don't use an external relay, the broadcast messages need to be sent continuously
if c.Options.OnlyLocal {
timeLimit = -1 * time.Second
} else {
@ -440,10 +593,10 @@ func (c *Client) transferOverLocalRelay(errchan chan<- error) {
time.Sleep(500 * time.Millisecond)
log.Debug("establishing connection")
var banner string
conn, banner, ipaddr, err := tcp.ConnectToTCPServer("localhost:"+c.Options.RelayPorts[0], c.Options.RelayPassword, c.Options.SharedSecret[:3])
conn, banner, ipaddr, err := tcp.ConnectToTCPServer("127.0.0.1:"+c.Options.RelayPorts[0], c.Options.RelayPassword, c.Options.RoomName)
log.Debugf("banner: %s", banner)
if err != nil {
err = fmt.Errorf("could not connect to localhost:%s: %w", c.Options.RelayPorts[0], err)
err = fmt.Errorf("could not connect to 127.0.0.1:%s: %w", c.Options.RelayPorts[0], err)
log.Debug(err)
// not really an error because it will try to connect over the actual relay
return
@ -461,7 +614,7 @@ func (c *Client) transferOverLocalRelay(errchan chan<- error) {
}
c.conn[0] = conn
log.Debug("exchanged header message")
c.Options.RelayAddress = "localhost"
c.Options.RelayAddress = "127.0.0.1"
c.Options.RelayPorts = strings.Split(banner, ",")
if c.Options.NoMultiplexing {
log.Debug("no multiplexing")
@ -477,12 +630,11 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
c.TotalNumberFolders = totalNumberFolders
c.TotalNumberOfContents = len(filesInfo)
err = c.sendCollectFiles(filesInfo)
if err != nil {
return
}
flags := &strings.Builder{}
if c.Options.RelayAddress != models.DEFAULT_RELAY {
if c.Options.RelayAddress != models.DEFAULT_RELAY && !c.Options.OnlyLocal {
flags.WriteString("--relay " + c.Options.RelayAddress + " ")
}
if c.Options.RelayPassword != models.DEFAULT_PASSPHRASE {
@ -529,7 +681,7 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
log.Debugf("got host '%v' and port '%v'", host, port)
address = net.JoinHostPort(host, port)
log.Debugf("trying connection to %s", address)
conn, banner, ipaddr, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.SharedSecret[:3], durations[i])
conn, banner, ipaddr, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.RoomName, durations[i])
if err == nil {
c.Options.RelayAddress = address
break
@ -547,13 +699,34 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
}
log.Debugf("banner: %s", banner)
log.Debugf("connection established: %+v", conn)
var kB []byte
B, _ := pake.InitCurve([]byte(c.Options.SharedSecret[5:]), 1, c.Options.Curve)
for {
log.Debug("waiting for bytes")
var dataMessage SimpleMessage
log.Trace("waiting for bytes")
data, errConn := conn.Receive()
if errConn != nil {
log.Debugf("[%+v] had error: %s", conn, errConn.Error())
log.Tracef("[%+v] had error: %s", conn, errConn.Error())
}
json.Unmarshal(data, &dataMessage)
log.Tracef("data: %+v '%s'", data, data)
log.Tracef("dataMessage: %s", dataMessage)
log.Tracef("kB: %x", kB)
// if kB not null, then use it to decrypt
if kB != nil {
var decryptErr error
var dataDecrypt []byte
dataDecrypt, decryptErr = crypt.Decrypt(data, kB)
if decryptErr != nil {
log.Tracef("error decrypting: %v: '%s'", decryptErr, data)
} else {
// copy dataDecrypt to data
data = dataDecrypt
log.Tracef("decrypted: %s", data)
}
}
if bytes.Equal(data, ipRequest) {
log.Tracef("got ipRequest")
// recipient wants to try to connect to local ips
var ips []string
// only get local ips if the local is enabled
@ -561,22 +734,48 @@ func (c *Client) Send(filesInfo []FileInfo, emptyFoldersToTransfer []FileInfo, t
// get list of local ips
ips, err = utils.GetLocalIPs()
if err != nil {
log.Debugf("error getting local ips: %v", err)
log.Tracef("error getting local ips: %v", err)
}
// prepend the port that is being listened to
ips = append([]string{c.Options.RelayPorts[0]}, ips...)
}
bips, _ := json.Marshal(ips)
if err := conn.Send(bips); err != nil {
log.Tracef("sending ips: %+v", ips)
bips, errIps := json.Marshal(ips)
if errIps != nil {
log.Tracef("error marshalling ips: %v", errIps)
}
bips, errIps = crypt.Encrypt(bips, kB)
if errIps != nil {
log.Tracef("error encrypting ips: %v", errIps)
}
if err = conn.Send(bips); err != nil {
log.Errorf("error sending: %v", err)
}
} else if dataMessage.Kind == "pake1" {
log.Trace("got pake1")
var pakeError error
pakeError = B.Update(dataMessage.Bytes)
if pakeError == nil {
kB, pakeError = B.SessionKey()
if pakeError == nil {
log.Tracef("dataMessage kB: %x", kB)
dataMessage.Bytes = B.Bytes()
dataMessage.Kind = "pake2"
data, _ = json.Marshal(dataMessage)
if pakeError = conn.Send(data); err != nil {
log.Errorf("dataMessage error sending: %v", err)
}
}
}
} else if bytes.Equal(data, handshakeRequest) {
log.Trace("got handshake")
break
} else if bytes.Equal(data, []byte{1}) {
log.Debug("got ping")
log.Trace("got ping")
continue
} else {
log.Debugf("[%+v] got weird bytes: %+v", conn, data)
log.Tracef("[%+v] got weird bytes: %+v", conn, data)
// throttle the reading
errchan <- fmt.Errorf("gracefully refusing using the public relay")
return
@ -726,7 +925,7 @@ func (c *Client) Receive() (err error) {
log.Debugf("got host '%v' and port '%v'", host, port)
address = net.JoinHostPort(host, port)
log.Debugf("trying connection to %s", address)
c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.SharedSecret[:3], durations[i])
c.conn[0], banner, c.ExternalIP, err = tcp.ConnectToTCPServer(address, c.Options.RelayPassword, c.Options.RoomName, durations[i])
if err == nil {
c.Options.RelayAddress = address
break
@ -741,23 +940,74 @@ func (c *Client) Receive() (err error) {
log.Debugf("receiver connection established: %+v", c.conn[0])
log.Debugf("banner: %s", banner)
if !usingLocal && !c.Options.DisableLocal && !isIPset {
if c.Options.TestFlag {
log.Debugf("TEST FLAG ENABLED, TESTING LOCAL IPS")
}
if c.Options.TestFlag || (!usingLocal && !c.Options.DisableLocal && !isIPset) {
// ask the sender for their local ips and port
// and try to connect to them
log.Debug("sending ips?")
var data []byte
if err := c.conn[0].Send(ipRequest); err != nil {
log.Errorf("ips send error: %v", err)
}
data, err = c.conn[0].Receive()
if err != nil {
return
}
log.Debugf("ips data: %s", data)
var ips []string
if err := json.Unmarshal(data, &ips); err != nil {
log.Debugf("ips unmarshal error: %v", err)
}
err = func() (err error) {
var A *pake.Pake
var data []byte
A, err = pake.InitCurve([]byte(c.Options.SharedSecret[5:]), 0, c.Options.Curve)
if err != nil {
return err
}
dataMessage := SimpleMessage{
Bytes: A.Bytes(),
Kind: "pake1",
}
data, _ = json.Marshal(dataMessage)
if err = c.conn[0].Send(data); err != nil {
log.Errorf("dataMessage send error: %v", err)
return
}
data, err = c.conn[0].Receive()
if err != nil {
return
}
err = json.Unmarshal(data, &dataMessage)
if err != nil || dataMessage.Kind != "pake2" {
log.Debugf("data: %s", data)
return fmt.Errorf("dataMessage %s pake failed", ipRequest)
}
err = A.Update(dataMessage.Bytes)
if err != nil {
return
}
var kA []byte
kA, err = A.SessionKey()
if err != nil {
return
}
log.Debugf("dataMessage kA: %x", kA)
// secure ipRequest
data, err = crypt.Encrypt([]byte(ipRequest), kA)
if err != nil {
return
}
log.Debug("sending ips?")
if err = c.conn[0].Send(data); err != nil {
log.Errorf("ips send error: %v", err)
}
data, err = c.conn[0].Receive()
if err != nil {
return
}
data, err = crypt.Decrypt(data, kA)
if err != nil {
return
}
log.Debugf("ips data: %s", data)
if err = json.Unmarshal(data, &ips); err != nil {
log.Debugf("ips unmarshal error: %v", err)
}
return
}()
if len(ips) > 1 {
port := ips[0]
ips = ips[1:]
@ -768,8 +1018,10 @@ func (c *Client) Receive() (err error) {
haveLocalIP := false
for _, localIP := range localIps {
localIPparsed := net.ParseIP(localIP)
log.Debugf("localIP: %+v, localIPparsed: %+v", localIP, localIPparsed)
if ipv4Net.Contains(localIPparsed) {
haveLocalIP = true
log.Debugf("ip: %+v is a local IP", ip)
break
}
}
@ -778,8 +1030,8 @@ func (c *Client) Receive() (err error) {
continue
}
serverTry := fmt.Sprintf("%s:%s", ip, port)
conn, banner2, externalIP, errConn := tcp.ConnectToTCPServer(serverTry, c.Options.RelayPassword, c.Options.SharedSecret[:3], 500*time.Millisecond)
serverTry := net.JoinHostPort(ip, port)
conn, banner2, externalIP, errConn := tcp.ConnectToTCPServer(serverTry, c.Options.RelayPassword, c.Options.RoomName, 500*time.Millisecond)
if errConn != nil {
log.Debug(errConn)
log.Debugf("could not connect to " + serverTry)
@ -799,7 +1051,7 @@ func (c *Client) Receive() (err error) {
}
}
if err := c.conn[0].Send(handshakeRequest); err != nil {
if err = c.conn[0].Send(handshakeRequest); err != nil {
log.Errorf("handshake send error: %v", err)
}
c.Options.RelayPorts = strings.Split(banner, ",")
@ -812,7 +1064,7 @@ func (c *Client) Receive() (err error) {
err = c.transfer()
if err == nil {
if c.numberOfTransferredFiles+len(c.EmptyFoldersToTransfer) == 0 {
fmt.Fprintf(os.Stderr, "\rNo files transferred.")
fmt.Fprintf(os.Stderr, "\rNo files transferred.\n")
}
}
return
@ -851,6 +1103,7 @@ func (c *Client) transfer() (err error) {
}
done, err = c.processMessage(data)
if err != nil {
log.Debugf("data: %s", data)
log.Debugf("got error processing: %v", err)
break
}
@ -865,6 +1118,24 @@ func (c *Client) transfer() (err error) {
}
err = nil
}
if c.Options.IsSender && c.SuccessfulTransfer {
for _, file := range c.FilesToTransfer {
if file.TempFile {
fmt.Println("Removing " + file.Name)
os.Remove(file.Name)
}
}
}
if c.SuccessfulTransfer && !c.Options.IsSender {
for _, file := range c.FilesToTransfer {
if file.TempFile {
utils.UnzipDirectory(".", file.Name)
os.Remove(file.Name)
log.Debugf("Removing %s\n", file.Name)
}
}
}
if c.Options.Stdout && !c.Options.IsSender {
pathToFile := path.Join(
@ -877,10 +1148,10 @@ func (c *Client) transfer() (err error) {
c.CurrentFile.Close()
c.CurrentFileIsClosed = true
}
if err := os.Remove(pathToFile); err != nil {
if err = os.Remove(pathToFile); err != nil {
log.Warnf("error removing %s: %v", pathToFile, err)
}
fmt.Print("\n")
fmt.Fprint(os.Stderr, "\n")
}
if err != nil && strings.Contains(err.Error(), "pake not successful") {
log.Debugf("pake error: %s", err.Error())
@ -888,7 +1159,7 @@ func (c *Client) transfer() (err error) {
}
if err != nil && strings.Contains(err.Error(), "unexpected end of JSON input") {
log.Debugf("error: %s", err.Error())
err = fmt.Errorf("room not ready")
err = fmt.Errorf("room (secure channel) not ready, maybe peer disconnected")
}
return
}
@ -928,6 +1199,21 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
c.EmptyFoldersToTransfer = senderInfo.EmptyFoldersToTransfer
c.TotalNumberFolders = senderInfo.TotalNumberFolders
c.FilesToTransfer = senderInfo.FilesToTransfer
for i, fi := range c.FilesToTransfer {
// Issues #593 - sanitize the sender paths and prevent ".." from being used
c.FilesToTransfer[i].FolderRemote = filepath.Clean(fi.FolderRemote)
if strings.Contains(c.FilesToTransfer[i].FolderRemote, "..") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
// Issues #593 - disallow specific folders like .ssh
if strings.Contains(c.FilesToTransfer[i].FolderRemote, ".ssh") {
return true, fmt.Errorf("invalid path detected: '%s'", fi.FolderRemote)
}
// Issue #595 - disallow filenames with invisible characters
if !utils.ValidFileName(path.Join(c.FilesToTransfer[i].FolderRemote, fi.Name)) {
return true, fmt.Errorf("invalid filename detected: '%s'", fi.Name)
}
}
c.TotalNumberOfContents = 0
if c.FilesToTransfer != nil {
c.TotalNumberOfContents += len(c.FilesToTransfer)
@ -976,7 +1262,11 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
machID, _ := machineid.ID()
fmt.Fprintf(os.Stderr, "\rYour machine id is '%s'.\n%s %s (%s) from '%s'? (Y/n) ", machID, action, fname, utils.ByteCountDecimal(totalSize), senderInfo.MachineID)
} else {
fmt.Fprintf(os.Stderr, "\r%s %s and %s (%s)? (Y/n) ", action, fname, folderName, utils.ByteCountDecimal(totalSize))
if c.TotalNumberFolders > 0 {
fmt.Fprintf(os.Stderr, "\r%s %s and %s (%s)? (Y/n) ", action, fname, folderName, utils.ByteCountDecimal(totalSize))
} else {
fmt.Fprintf(os.Stderr, "\r%s %s (%s)? (Y/n) ", action, fname, utils.ByteCountDecimal(totalSize))
}
}
choice := strings.ToLower(utils.GetInput(""))
if choice != "" && choice != "y" && choice != "yes" {
@ -1018,7 +1308,7 @@ func (c *Client) processMessageFileInfo(m message.Message) (done bool, err error
}
}
// if no files are to be transfered, then we can end the file transfer process
// if no files are to be transferred, then we can end the file transfer process
if c.FilesToTransfer == nil {
c.SuccessfulTransfer = true
c.Step3RecipientRequestFile = true
@ -1093,7 +1383,7 @@ func (c *Client) processMessagePake(m message.Message) (err error) {
go func(j int) {
defer wg.Done()
var host string
if c.Options.RelayAddress == "localhost" {
if c.Options.RelayAddress == "127.0.0.1" {
host = c.Options.RelayAddress
} else {
host, _, err = net.SplitHostPort(c.Options.RelayAddress)
@ -1107,7 +1397,7 @@ func (c *Client) processMessagePake(m message.Message) (err error) {
c.conn[j+1], _, _, err = tcp.ConnectToTCPServer(
server,
c.Options.RelayPassword,
fmt.Sprintf("%s-%d", utils.SHA256(c.Options.SharedSecret[:5])[:6], j),
fmt.Sprintf("%s-%d", c.Options.RoomName, j),
)
if err != nil {
panic(err)
@ -1296,7 +1586,7 @@ func (c *Client) recipientInitializeFile() (err error) {
var errOpen error
c.CurrentFile, errOpen = os.OpenFile(
pathToFile,
os.O_WRONLY, 0666)
os.O_WRONLY, 0o666)
var truncate bool // default false
c.CurrentFileChunks = []int64{}
c.CurrentFileChunkRanges = []int64{}
@ -1319,6 +1609,10 @@ func (c *Client) recipientInitializeFile() (err error) {
log.Error(errOpen)
return errOpen
}
errChmod := os.Chmod(pathToFile, c.FilesToTransfer[c.FilesToTransferCurrentNum].Mode.Perm())
if errChmod != nil {
log.Error(errChmod)
}
truncate = true
}
if truncate {
@ -1344,6 +1638,7 @@ func (c *Client) recipientGetFileReady(finished bool) (err error) {
}
c.SuccessfulTransfer = true
c.FilesHasFinished[c.FilesToTransferCurrentNum] = struct{}{}
return
}
err = c.recipientInitializeFile()
@ -1416,6 +1711,9 @@ func (c *Client) createEmptyFileAndFinish(fileInfo FileInfo, i int) (err error)
} else {
description = " " + description
}
if len(description) > 20 {
description = description[:17] + "..."
}
c.bar = progressbar.NewOptions64(1,
progressbar.OptionOnCompletion(func() {
c.fmtPrintUpdate()
@ -1433,7 +1731,7 @@ func (c *Client) createEmptyFileAndFinish(fileInfo FileInfo, i int) (err error)
}
func (c *Client) updateIfRecipientHasFileInfo() (err error) {
if !(!c.Options.IsSender && c.Step2FileInfoTransferred && !c.Step3RecipientRequestFile) {
if c.Options.IsSender || !c.Step2FileInfoTransferred || c.Step3RecipientRequestFile {
return
}
// find the next file to transfer and send that number
@ -1483,7 +1781,7 @@ func (c *Client) updateIfRecipientHasFileInfo() (err error) {
}
choice := strings.ToLower(utils.GetInput(prompt))
if choice != "y" && choice != "yes" {
fmt.Fprintf(os.Stderr, "skipping '%s'", path.Join(fileInfo.FolderRemote, fileInfo.Name))
fmt.Fprintf(os.Stderr, "Skipping '%s'\n", path.Join(fileInfo.FolderRemote, fileInfo.Name))
continue
}
}
@ -1571,7 +1869,6 @@ func (c *Client) updateState() (err error) {
c.FilesToTransfer[c.FilesToTransferCurrentNum].FolderSource,
c.FilesToTransfer[c.FilesToTransferCurrentNum].Name,
)
c.fread, err = os.Open(pathToFile)
c.numfinished = 0
if err != nil {
@ -1593,6 +1890,9 @@ func (c *Client) setBar() {
} else if !c.Options.IsSender {
description = " " + description
}
if len(description) > 20 {
description = description[:17] + "..."
}
c.bar = progressbar.NewOptions64(
c.FilesToTransfer[c.FilesToTransferCurrentNum].Size,
progressbar.OptionOnCompletion(func() {
@ -1620,14 +1920,14 @@ func (c *Client) setBar() {
}
func (c *Client) receiveData(i int) {
log.Debugf("%d receiving data", i)
log.Tracef("%d receiving data", i)
for {
data, err := c.conn[i+1].Receive()
if err != nil {
break
}
if bytes.Equal(data, []byte{1}) {
log.Debug("got ping")
log.Trace("got ping")
continue
}
@ -1661,7 +1961,7 @@ func (c *Client) receiveData(i int) {
if !c.CurrentFileIsClosed && (c.TotalChunksTransferred == len(c.CurrentFileChunks) || c.TotalSent == c.FilesToTransfer[c.FilesToTransferCurrentNum].Size) {
c.CurrentFileIsClosed = true
log.Debug("finished receiving!")
if err := c.CurrentFile.Close(); err != nil {
if err = c.CurrentFile.Close(); err != nil {
log.Debugf("error closing %s: %v", c.CurrentFile.Name(), err)
} else {
log.Debugf("Successful closing %s", c.CurrentFile.Name())
@ -1703,62 +2003,66 @@ func (c *Client) sendData(i int) {
curi := float64(0)
for {
// Read file
data := make([]byte, models.TCP_BUFFER_SIZE/2)
// log.Debugf("%d trying to read", i)
n, errRead := c.fread.ReadAt(data, readingPos)
// log.Debugf("%d read %d bytes", i, n)
readingPos += int64(n)
if c.limiter != nil {
r := c.limiter.ReserveN(time.Now(), n)
log.Debugf("Limiting Upload for %d", r.Delay())
time.Sleep(r.Delay())
}
var n int
var errRead error
if math.Mod(curi, float64(len(c.Options.RelayPorts))) == float64(i) {
// check to see if this is a chunk that the recipient wants
usableChunk := true
c.mutex.Lock()
if len(c.chunkMap) != 0 {
if _, ok := c.chunkMap[pos]; !ok {
usableChunk = false
} else {
delete(c.chunkMap, pos)
}
data := make([]byte, models.TCP_BUFFER_SIZE/2)
n, errRead = c.fread.ReadAt(data, readingPos)
if c.limiter != nil {
r := c.limiter.ReserveN(time.Now(), n)
log.Debugf("Limiting Upload for %d", r.Delay())
time.Sleep(r.Delay())
}
c.mutex.Unlock()
if usableChunk {
// log.Debugf("sending chunk %d", pos)
posByte := make([]byte, 8)
binary.LittleEndian.PutUint64(posByte, pos)
var err error
var dataToSend []byte
if c.Options.NoCompress {
dataToSend, err = crypt.Encrypt(
append(posByte, data[:n]...),
c.Key,
)
} else {
dataToSend, err = crypt.Encrypt(
compress.Compress(
if n > 0 {
// check to see if this is a chunk that the recipient wants
usableChunk := true
c.mutex.Lock()
if len(c.chunkMap) != 0 {
if _, ok := c.chunkMap[pos]; !ok {
usableChunk = false
} else {
delete(c.chunkMap, pos)
}
}
c.mutex.Unlock()
if usableChunk {
// log.Debugf("sending chunk %d", pos)
posByte := make([]byte, 8)
binary.LittleEndian.PutUint64(posByte, pos)
var err error
var dataToSend []byte
if c.Options.NoCompress {
dataToSend, err = crypt.Encrypt(
append(posByte, data[:n]...),
),
c.Key,
)
}
if err != nil {
panic(err)
}
c.Key,
)
} else {
dataToSend, err = crypt.Encrypt(
compress.Compress(
append(posByte, data[:n]...),
),
c.Key,
)
}
if err != nil {
panic(err)
}
err = c.conn[i+1].Send(dataToSend)
if err != nil {
panic(err)
err = c.conn[i+1].Send(dataToSend)
if err != nil {
panic(err)
}
c.bar.Add(n)
c.TotalSent += int64(n)
// time.Sleep(100 * time.Millisecond)
}
c.bar.Add(n)
c.TotalSent += int64(n)
// time.Sleep(100 * time.Millisecond)
}
}
if n == 0 {
n = models.TCP_BUFFER_SIZE / 2
}
readingPos += int64(n)
curi++
pos += uint64(n)

View File

@ -5,11 +5,12 @@ import (
"path"
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
"time"
"github.com/schollz/croc/v9/src/tcp"
"github.com/schollz/croc/v10/src/tcp"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
@ -17,11 +18,11 @@ import (
func init() {
log.SetLevel("trace")
go tcp.Run("debug", "localhost", "8281", "pass123", "8282,8283,8284,8285")
go tcp.Run("debug", "localhost", "8282", "pass123")
go tcp.Run("debug", "localhost", "8283", "pass123")
go tcp.Run("debug", "localhost", "8284", "pass123")
go tcp.Run("debug", "localhost", "8285", "pass123")
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)
}
@ -33,7 +34,7 @@ func TestCrocReadme(t *testing.T) {
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
@ -41,6 +42,7 @@ func TestCrocReadme(t *testing.T) {
DisableLocal: true,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
@ -51,7 +53,7 @@ func TestCrocReadme(t *testing.T) {
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
@ -66,7 +68,7 @@ func TestCrocReadme(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../README.md"})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../README.md"}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
@ -92,14 +94,14 @@ func TestCrocEmptyFolder(t *testing.T) {
pathName := "../../testEmpty"
defer os.RemoveAll(pathName)
defer os.RemoveAll("./testEmpty")
os.MkdirAll(pathName, 0755)
os.MkdirAll(pathName, 0o755)
log.Debug("setting up sender")
sender, err := New(Options{
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
@ -117,7 +119,7 @@ func TestCrocEmptyFolder(t *testing.T) {
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
@ -132,7 +134,7 @@ func TestCrocEmptyFolder(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{pathName})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{pathName}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
@ -158,7 +160,7 @@ func TestCrocSymlink(t *testing.T) {
pathName := "../link-in-folder"
defer os.RemoveAll(pathName)
defer os.RemoveAll("./link-in-folder")
os.MkdirAll(pathName, 0755)
os.MkdirAll(pathName, 0o755)
os.Symlink("../../README.md", filepath.Join(pathName, "README.link"))
log.Debug("setting up sender")
@ -166,7 +168,7 @@ func TestCrocSymlink(t *testing.T) {
IsSender: true,
SharedSecret: "8124-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPorts: []string{"8281"},
RelayPassword: "pass123",
Stdout: false,
@ -174,6 +176,7 @@ func TestCrocSymlink(t *testing.T) {
DisableLocal: true,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
@ -184,7 +187,7 @@ func TestCrocSymlink(t *testing.T) {
IsSender: false,
SharedSecret: "8124-testingthecroc",
Debug: true,
RelayAddress: "localhost:8281",
RelayAddress: "127.0.0.1:8281",
RelayPassword: "pass123",
Stdout: false,
NoPrompt: true,
@ -199,11 +202,11 @@ func TestCrocSymlink(t *testing.T) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{pathName})
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)
err = sender.Send(filesInfo, emptyFolders, totalNumberFolders)
if err != nil {
t.Errorf("send failed: %v", err)
}
@ -211,7 +214,7 @@ func TestCrocSymlink(t *testing.T) {
}()
time.Sleep(100 * time.Millisecond)
go func() {
err := receiver.Receive()
err = receiver.Receive()
if err != nil {
t.Errorf("receive failed: %v", err)
}
@ -229,6 +232,32 @@ func TestCrocSymlink(t *testing.T) {
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 TestCrocLocal(t *testing.T) {
log.SetLevel("trace")
@ -241,7 +270,7 @@ func TestCrocLocal(t *testing.T) {
IsSender: true,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8181",
RelayAddress: "127.0.0.1:8181",
RelayPorts: []string{"8181", "8182"},
RelayPassword: "pass123",
Stdout: true,
@ -249,6 +278,7 @@ func TestCrocLocal(t *testing.T) {
DisableLocal: false,
Curve: "siec",
Overwrite: true,
GitIgnore: false,
})
if err != nil {
panic(err)
@ -260,7 +290,7 @@ func TestCrocLocal(t *testing.T) {
IsSender: false,
SharedSecret: "8123-testingthecroc",
Debug: true,
RelayAddress: "localhost:8181",
RelayAddress: "127.0.0.1:8181",
RelayPassword: "pass123",
Stdout: true,
NoPrompt: true,
@ -276,7 +306,7 @@ func TestCrocLocal(t *testing.T) {
os.Create("touched")
wg.Add(2)
go func() {
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../LICENSE", "touched"})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{"../../LICENSE", "touched"}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
@ -307,10 +337,10 @@ func TestCrocError(t *testing.T) {
defer os.Remove(tmpfile.Name()) // clean up
if _, err := tmpfile.Write(content); err != nil {
if _, err = tmpfile.Write(content); err != nil {
panic(err)
}
if err := tmpfile.Close(); err != nil {
if err = tmpfile.Close(); err != nil {
panic(err)
}
@ -329,7 +359,7 @@ func TestCrocError(t *testing.T) {
Curve: "siec",
Overwrite: true,
})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{tmpfile.Name()})
filesInfo, emptyFolders, totalNumberFolders, errGet := GetFilesInfo([]string{tmpfile.Name()}, false, false)
if errGet != nil {
t.Errorf("failed to get minimal info: %v", errGet)
}
@ -353,7 +383,7 @@ func TestCleanUp(t *testing.T) {
for _, file := range []string{"README.md", "./README.md"} {
err = os.Remove(file)
if err == nil {
log.Debugf("Successfuly purged %s", file)
log.Debugf("Successfully purged %s", file)
} else {
log.Debugf("%s was already purged.", file)
}
@ -361,7 +391,7 @@ func TestCleanUp(t *testing.T) {
for _, folder := range []string{"./testEmpty", "./link-in-folder"} {
err = os.RemoveAll(folder)
if err == nil {
log.Debugf("Successfuly purged %s", folder)
log.Debugf("Successfully purged %s", folder)
} else {
log.Debugf("%s was already purged.", folder)
}

View File

@ -39,7 +39,7 @@ func Encrypt(plaintext []byte, key []byte) (encrypted []byte, err error) {
// http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
// Section 8.2
ivBytes := make([]byte, 12)
if _, err := rand.Read(ivBytes); err != nil {
if _, err = rand.Read(ivBytes); err != nil {
log.Fatalf("can't initialize crypto: %v", err)
}
b, err := aes.NewCipher(key)
@ -85,7 +85,7 @@ func NewArgon2(passphrase []byte, usersalt []byte) (aead cipher.AEAD, salt []byt
salt = make([]byte, 8)
// http://www.ietf.org/rfc/rfc2898.txt
// Salt.
if _, err := rand.Read(salt); err != nil {
if _, err = rand.Read(salt); err != nil {
log.Fatalf("can't get random salt: %v", err)
}
} else {

View File

@ -52,19 +52,19 @@ func TestEncryption(t *testing.T) {
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, err := New([]byte("password"), 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, _, err = New([]byte("wrong password"), 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
dec, err = Decrypt([]byte(""), key)
_, err = Decrypt([]byte(""), key)
assert.NotNil(t, err)
// error with small password
@ -84,19 +84,19 @@ func TestEncryptionChaCha(t *testing.T) {
assert.Equal(t, msg, dec)
// check reusing the salt
key2, _, err := NewArgon2([]byte("password"), 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, _, err = NewArgon2([]byte("wrong password"), 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
dec, err = DecryptChaCha([]byte(""), key)
_, err = DecryptChaCha([]byte(""), key)
assert.NotNil(t, err)
// error with small password

View File

@ -13,5 +13,7 @@ release:
cd ../../ && ./src/install/upload-src-tarball.sh
test:
cp zsh_autocomplete ../../
cp bash_autocomplete ../../
cd ../../ && go generate
cd ../../ && goreleaser release --skip-publish

View File

@ -86,7 +86,7 @@ print_help() {
Default = /usr/local/bin ('\${PREFIX}/bin' on Termux for Android)
-h
Prints this helpfull message and exit."
Prints this helpful message and exit."
echo "${help_header}"
echo ""
@ -156,7 +156,7 @@ make_tempdir() {
#--- FUNCTION ----------------------------------------------------------------
# NAME: determine_os
# DESCRIPTION: Attempts to determin host os using uname
# DESCRIPTION: Attempts to determine host os using uname
# PARAMETERS: none
# RETURNS: 0 = OS Detected. Also prints detected os to stdout
# 1 = Unknown OS
@ -180,7 +180,7 @@ determine_os() {
#--- FUNCTION ----------------------------------------------------------------
# NAME: determine_arch
# DESCRIPTION: Attempt to determin architecture of host
# DESCRIPTION: Attempt to determine architecture of host
# PARAMETERS: none
# RETURNS: 0 = Arch Detected. Also prints detected arch to stdout
# 1 = Unknown arch
@ -300,10 +300,10 @@ checksum_check() {
#--- FUNCTION ----------------------------------------------------------------
# NAME: extract_file
# DESCRIPTION: Extracts a file into a location. Attempts to determine which
# tool to use by checking file extention.
# tool to use by checking file extension.
# PARAMETERS: $1 = file to extract
# $2 = location to extract file into
# $3 = extention
# $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
@ -528,7 +528,7 @@ main() {
local autocomplete_install_rcode
croc_bin_name="croc"
croc_version="9.5.5"
croc_version="10.0.7"
croc_dl_ext="tar.gz"
croc_base_url="https://github.com/schollz/croc/releases/download"
prefix="${1}"
@ -587,16 +587,17 @@ main() {
"x86_64" ) croc_arch="64bit";;
"amd64" ) croc_arch="64bit";;
"aarch64" ) croc_arch="ARM64";;
"arm64" ) croc_arch="ARM64";;
"armv7l" ) croc_arch="ARM";;
"i686" ) croc_arch="32bit";;
* ) croc_arch="unknown";;
esac
croc_file="${croc_bin_name}_${croc_version}_${croc_os}-${croc_arch}.${croc_dl_ext}"
croc_checksum_file="${croc_bin_name}_${croc_version}_checksums.txt"
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
@ -712,27 +713,27 @@ main() {
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
# 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
# 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"

View File

@ -57,7 +57,7 @@ func replaceInFile(fname, start, end, replacement string) (err error) {
fmt.Sprintf("%s%s%s", start, replacement, end),
1,
)
err = os.WriteFile(fname, []byte(newF), 0644)
err = os.WriteFile(fname, []byte(newF), 0o644)
return
}

View File

@ -3,9 +3,9 @@ package message
import (
"encoding/json"
"github.com/schollz/croc/v9/src/comm"
"github.com/schollz/croc/v9/src/compress"
"github.com/schollz/croc/v9/src/crypt"
"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"
)

View File

@ -7,8 +7,8 @@ import (
"testing"
"time"
"github.com/schollz/croc/v9/src/comm"
"github.com/schollz/croc/v9/src/crypt"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/crypt"
log "github.com/schollz/logger"
"github.com/stretchr/testify/assert"
)
@ -20,7 +20,7 @@ func TestMessage(t *testing.T) {
m := Message{Type: TypeMessage, Message: "hello, world"}
e, salt, err := crypt.New([]byte("pass"), nil)
assert.Nil(t, err)
fmt.Println(salt)
fmt.Println(string(salt))
b, err := Encode(e, m)
assert.Nil(t, err)
fmt.Printf("%x\n", b)
@ -67,7 +67,7 @@ func TestSend(t *testing.T) {
log.Error(err)
}
log.Debugf("client %s connected", connection.RemoteAddr().String())
go func(port string, connection net.Conn) {
go func(_ string, connection net.Conn) {
c := comm.New(connection)
err = c.Send([]byte("hello, world"))
assert.Nil(t, err)
@ -84,8 +84,8 @@ func TestSend(t *testing.T) {
}
}()
time.Sleep(300 * time.Millisecond)
a, err := comm.NewConnection("localhost:"+port, 10*time.Minute)
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)

View File

@ -7,7 +7,7 @@ import (
"os"
"path"
"github.com/schollz/croc/v9/src/utils"
"github.com/schollz/croc/v10/src/utils"
)
// TCP_BUFFER_SIZE is the maximum packet size
@ -22,8 +22,8 @@ var (
INTERNAL_DNS = false
)
// publicDns are servers to be queried if a local lookup fails
var publicDns = []string{
// 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
@ -44,8 +44,8 @@ var publicDns = []string{
"[2620:119:53::53]", // Cisco OpenDNS
}
func getConfigFile() (fname string, err error) {
configFile, err := utils.GetConfigDir()
func getConfigFile(requireValidPath bool) (fname string, err error) {
configFile, err := utils.GetConfigDir(requireValidPath)
if err != nil {
return
}
@ -66,28 +66,29 @@ func init() {
}
if doRemember {
// save in config file
fname, err := getConfigFile()
fname, err := getConfigFile(true)
if err == nil {
f, _ := os.Create(fname)
f.Close()
}
}
if !INTERNAL_DNS {
fname, err := getConfigFile()
fname, err := getConfigFile(false)
if err == nil {
INTERNAL_DNS = utils.Exists(fname)
}
}
var err error
DEFAULT_RELAY, err = lookup(DEFAULT_RELAY)
var addr string
addr, err = lookup(DEFAULT_RELAY)
if err == nil {
DEFAULT_RELAY += ":" + DEFAULT_PORT
DEFAULT_RELAY = net.JoinHostPort(addr, DEFAULT_PORT)
} else {
DEFAULT_RELAY = ""
}
DEFAULT_RELAY6, err = lookup(DEFAULT_RELAY6)
addr, err = lookup(DEFAULT_RELAY6)
if err == nil {
DEFAULT_RELAY6 = "[" + DEFAULT_RELAY6 + "]:" + DEFAULT_PORT
DEFAULT_RELAY6 = net.JoinHostPort(addr, DEFAULT_PORT)
} else {
DEFAULT_RELAY6 = ""
}
@ -102,15 +103,15 @@ func lookup(address string) (ipaddress string, err error) {
s string
err error
}
result := make(chan Result, len(publicDns))
for _, dns := range publicDns {
result := make(chan Result, len(publicDNS))
for _, dns := range publicDNS {
go func(dns string) {
var r Result
r.s, r.err = remoteLookupIP(address, dns)
result <- r
}(dns)
}
for i := 0; i < len(publicDns); i++ {
for i := 0; i < len(publicDNS); i++ {
ipaddress = (<-result).s
if ipaddress != "" {
return
@ -134,7 +135,7 @@ func localLookupIP(address string) (ipaddress string, err error) {
func remoteLookupIP(address, dns string) (ipaddress string, err error) {
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
Dial: func(ctx context.Context, network, _ string) (net.Conn, error) {
d := new(net.Dialer)
return d.DialContext(ctx, network, dns+":53")
},

View File

@ -11,9 +11,9 @@ import (
log "github.com/schollz/logger"
"github.com/schollz/pake/v3"
"github.com/schollz/croc/v9/src/comm"
"github.com/schollz/croc/v9/src/crypt"
"github.com/schollz/croc/v9/src/models"
"github.com/schollz/croc/v10/src/comm"
"github.com/schollz/croc/v10/src/crypt"
"github.com/schollz/croc/v10/src/models"
)
type server struct {
@ -93,7 +93,8 @@ func (s *server) run() (err error) {
if s.host != "" {
ip := net.ParseIP(s.host)
if ip == nil {
tcpIP, err := net.ResolveIPAddr("ip", s.host)
var tcpIP *net.IPAddr
tcpIP, err = net.ResolveIPAddr("ip", s.host)
if err != nil {
return err
}
@ -227,7 +228,7 @@ func (s *server) clientCommunication(port string, c *comm.Comm) (room string, er
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 {
if err = c.Send(enc); err != nil {
return "", fmt.Errorf("send error: %w", err)
}
return
@ -350,11 +351,11 @@ func (s *server) deleteRoom(room string) {
}
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, 1)
if err := conn.SetReadDeadline(time.Now().Add(3 * time.Hour)); err != nil {
@ -515,7 +516,7 @@ func ConnectToTCPServer(address, password, room string, timelimit ...time.Durati
}
banner = strings.Split(string(data), "|||")[0]
ipaddr = strings.Split(string(data), "|||")[1]
log.Debug("sending room")
log.Debugf("sending room; %s", room)
bSend, err = crypt.Encrypt([]byte(room), strongKeyForEncryption)
if err != nil {
log.Debug(err)

View File

@ -12,11 +12,11 @@ import (
func BenchmarkConnection(b *testing.B) {
log.SetLevel("trace")
go Run("debug", "localhost", "8283", "pass123", "8284")
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("localhost:8283", "pass123", fmt.Sprintf("testroom%d", i), 1*time.Minute)
c, _, _, _ := ConnectToTCPServer("127.0.0.1:8283", "pass123", fmt.Sprintf("testroom%d", i), 1*time.Minute)
c.Close()
}
}
@ -24,22 +24,22 @@ func BenchmarkConnection(b *testing.B) {
func TestTCP(t *testing.T) {
log.SetLevel("error")
timeToRoomDeletion = 100 * time.Millisecond
go Run("debug", "localhost", "8381", "pass123", "8382")
go Run("debug", "127.0.0.1", "8381", "pass123", "8382")
time.Sleep(timeToRoomDeletion)
err := PingServer("localhost:8381")
err := PingServer("127.0.0.1:8381")
assert.Nil(t, err)
err = PingServer("localhost:8333")
err = PingServer("127.0.0.1:8333")
assert.NotNil(t, err)
time.Sleep(timeToRoomDeletion)
c1, banner, _, err := ConnectToTCPServer("localhost:8381", "pass123", "testRoom", 1*time.Minute)
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("localhost:8381", "pass123", "testRoom")
c2, _, _, err := ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom")
assert.Nil(t, err)
_, _, _, err = ConnectToTCPServer("localhost:8381", "pass123", "testRoom")
_, _, _, err = ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom")
assert.NotNil(t, err)
_, _, _, err = ConnectToTCPServer("localhost:8381", "pass123", "testRoom", 1*time.Nanosecond)
_, _, _, err = ConnectToTCPServer("127.0.0.1:8381", "pass123", "testRoom", 1*time.Nanosecond)
assert.NotNil(t, err)
// try sending data

View File

@ -1,8 +1,10 @@
package utils
import (
"archive/zip"
"bufio"
"bytes"
"compress/flate"
"crypto/md5"
"crypto/rand"
"crypto/sha256"
@ -16,31 +18,43 @@ import (
"net/http"
"os"
"path"
"path/filepath"
"strings"
"time"
"unicode"
"github.com/cespare/xxhash"
"github.com/kalafut/imohash"
"github.com/minio/highwayhash"
"github.com/schollz/mnemonicode"
"github.com/schollz/progressbar/v3"
)
// Get or create home directory
func GetConfigDir() (homedir string, err error) {
homedir, err = os.UserHomeDir()
if err != nil {
return
}
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 _, err = os.Stat(homedir); os.IsNotExist(err) {
err = os.MkdirAll(homedir, 0700)
if requireValidPath {
if _, err = os.Stat(homedir); os.IsNotExist(err) {
err = os.MkdirAll(homedir, 0o700)
}
}
return
}
@ -65,7 +79,11 @@ func GetInput(prompt string) string {
// 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) (hash256 []byte, err error) {
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 {
@ -83,16 +101,59 @@ func HashFile(fname string, algorithm string) (hash256 []byte, err error) {
case "imohash":
return IMOHashFile(fname)
case "md5":
return MD5HashFile(fname)
return MD5HashFile(fname, doShowProgress)
case "xxhash":
return XXHashFile(fname)
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) (hash256 []byte, err error) {
func MD5HashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
@ -100,8 +161,25 @@ func MD5HashFile(fname string) (hash256 []byte, err error) {
defer f.Close()
h := md5.New()
if _, err = io.Copy(h, f); err != nil {
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
}
}
hash256 = h.Sum(nil)
@ -125,7 +203,7 @@ func IMOHashFileFull(fname string) (hash []byte, err error) {
}
// XXHashFile returns the xxhash of a file
func XXHashFile(fname string) (hash256 []byte, err error) {
func XXHashFile(fname string, doShowProgress bool) (hash256 []byte, err error) {
f, err := os.Open(fname)
if err != nil {
return
@ -133,8 +211,25 @@ func XXHashFile(fname string) (hash256 []byte, err error) {
defer f.Close()
h := xxhash.New()
if _, err = io.Copy(h, f); err != nil {
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
}
}
hash256 = h.Sum(nil)
@ -183,7 +278,7 @@ func GenerateRandomPin() string {
s := ""
max := new(big.Int)
max.SetInt64(9)
for i := 0; i < 4; i++ {
for i := 0; i < NbPinNumbers; i++ {
v, err := rand.Int(rand.Reader, max)
if err != nil {
panic(err)
@ -196,7 +291,7 @@ func GenerateRandomPin() string {
// GetRandomName returns mnemonicoded random name
func GetRandomName() string {
var result []string
bs := make([]byte, 4)
bs := make([]byte, NbBytesWords)
rand.Read(bs)
result = mnemonicode.EncodeWordList(result, bs)
return GenerateRandomPin() + "-" + strings.Join(result, "-")
@ -265,7 +360,6 @@ func MissingChunks(fname string, fsize int64, chunkSize int) (chunkRanges []int6
}
}
chunkRanges = append(chunkRanges, int64(curCount+1))
chunks = chunkRanges
}
return
}
@ -354,7 +448,7 @@ func init() {
}
func IsLocalIP(ipaddress string) bool {
if strings.Contains(ipaddress, "localhost") {
if strings.Contains(ipaddress, "127.0.0.1") {
return true
}
host, _, _ := net.SplitHostPort(ipaddress)
@ -369,3 +463,127 @@ func IsLocalIP(ipaddress string) bool {
}
return false
}
func ZipDirectory(destination string, source string) (err error) {
if _, err = os.Stat(destination); err == nil {
log.Fatalf("%s file already exists!\n", destination)
}
fmt.Fprintf(os.Stderr, "Zipping %s to %s\n", source, destination)
file, err := os.Create(destination)
if err != nil {
log.Fatalln(err)
}
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.Fatalln(err)
}
if info.Mode().IsRegular() {
f1, err := os.Open(path)
if err != nil {
log.Fatalln(err)
}
defer f1.Close()
zipPath := strings.ReplaceAll(path, source, strings.TrimSuffix(destination, ".zip"))
zipPath = filepath.ToSlash(zipPath)
w1, err := writer.Create(zipPath)
if err != nil {
log.Fatalln(err)
}
if _, err := io.Copy(w1, f1); err != nil {
log.Fatalln(err)
}
fmt.Fprintf(os.Stderr, "\r\033[2K")
fmt.Fprintf(os.Stderr, "\rAdding %s", zipPath)
}
return nil
})
if err != nil {
log.Fatalln(err)
}
fmt.Fprintf(os.Stderr, "\n")
return nil
}
func UnzipDirectory(destination string, source string) error {
archive, err := zip.OpenReader(source)
if err != nil {
log.Fatalln(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.Fatalf("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.Fatalln(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.Fatalln(err)
}
fileInArchive, err := f.Open()
if err != nil {
log.Fatalln(err)
}
if _, err := io.Copy(dstFile, fileInArchive); err != nil {
log.Fatalln(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) bool {
clean1 := strings.Map(func(r rune) rune {
if unicode.IsGraphic(r) {
return r
}
return -1
}, fname)
clean2 := strings.Map(func(r rune) rune {
if unicode.IsPrint(r) {
return r
}
return -1
}, fname)
return (fname == clean1) && (fname == clean2)
}

View File

@ -17,14 +17,14 @@ const TCP_BUFFER_SIZE = 1024 * 64
var bigFileSize = 75000000
func bigFile() {
os.WriteFile("bigfile.test", bytes.Repeat([]byte("z"), bigFileSize), 0666)
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")
MD5HashFile("bigfile.test", false)
}
}
@ -32,7 +32,7 @@ func BenchmarkXXHash(b *testing.B) {
bigFile()
b.ResetTimer()
for i := 0; i < b.N; i++ {
XXHashFile("bigfile.test")
XXHashFile("bigfile.test", false)
}
}
@ -44,6 +44,14 @@ func BenchmarkImoHash(b *testing.B) {
}
}
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()
@ -78,10 +86,20 @@ func TestExists(t *testing.T) {
func TestMD5HashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := MD5HashFile("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")
_, 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)
}
@ -96,10 +114,10 @@ func TestIMOHashFile(t *testing.T) {
func TestXXHashFile(t *testing.T) {
bigFile()
defer os.Remove("bigfile.test")
b, err := XXHashFile("bigfile.test")
b, err := XXHashFile("bigfile.test", false)
assert.Nil(t, err)
assert.Equal(t, "4918740eb5ccb6f7", fmt.Sprintf("%x", b))
_, err = XXHashFile("nofile")
_, err = XXHashFile("nofile", false)
assert.NotNil(t, err)
}
@ -119,9 +137,9 @@ func TestMissingChunks(t *testing.T) {
rand.Seed(1)
bigBuff := make([]byte, fileSize)
rand.Read(bigBuff)
os.WriteFile("missing.test", bigBuff, 0644)
os.WriteFile("missing.test", bigBuff, 0o644)
empty := make([]byte, chunkSize)
f, err := os.OpenFile("missing.test", os.O_RDWR, 0644)
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 {
@ -178,10 +196,10 @@ func TestHashFile(t *testing.T) {
defer os.Remove(tmpfile.Name()) // clean up
if _, err := tmpfile.Write(content); err != nil {
if _, err = tmpfile.Write(content); err != nil {
panic(err)
}
if err := tmpfile.Close(); err != nil {
if err = tmpfile.Close(); err != nil {
panic(err)
}
hashed, err := HashFile(tmpfile.Name(), "xxhash")
@ -208,11 +226,37 @@ func TestGetRandomName(t *testing.T) {
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("localhost", 9009, 4)
assert.Equal(t, []int{9009, 9010, 9011, 9012}, openPorts)
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.True(t, ValidFileName("中文.csl"))
// contains regular characters
assert.True(t, ValidFileName("[something].csl"))
// contains regular characters
assert.True(t, ValidFileName("[(something)].csl"))
// contains invisible character
assert.False(t, ValidFileName("D中文.cslouglas"))
}