Compare commits
80 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
238f1f54d7 | ||
![]() |
5df8463b74 | ||
![]() |
8d8ad7fdb3 | ||
![]() |
f06b639542 | ||
![]() |
5fd2eac6eb | ||
![]() |
e0821c751d | ||
![]() |
3c1c2dc28c | ||
![]() |
13f9edd2ea | ||
![]() |
fd5b38f9ab | ||
![]() |
6661a58770 | ||
![]() |
b2b287e34f | ||
![]() |
9b8dee12ea | ||
![]() |
a98c9d1ce4 | ||
![]() |
f77f9f116a | ||
![]() |
afb004680b | ||
![]() |
6edc0b1eac | ||
![]() |
7c94f265e2 | ||
![]() |
d33c03cd2c | ||
![]() |
ecc6bcf736 | ||
![]() |
3e9a4d67f2 | ||
![]() |
ea87a778b3 | ||
![]() |
91cf01ec75 | ||
![]() |
7598063e36 | ||
![]() |
6672891490 | ||
![]() |
8139e3be01 | ||
![]() |
ac9f56945b | ||
![]() |
b42225be76 | ||
![]() |
1a5ec2de79 | ||
![]() |
216772361a | ||
![]() |
55c243a007 | ||
![]() |
ccd489ce2e | ||
![]() |
8026a79478 | ||
![]() |
92ab75f837 | ||
![]() |
011d97f843 | ||
![]() |
3782996376 | ||
![]() |
8f909b805b | ||
![]() |
178b73f210 | ||
![]() |
4c55145a07 | ||
![]() |
faa1141a2b | ||
![]() |
10977f056d | ||
![]() |
e2f9b75844 | ||
![]() |
e5fd4c237b | ||
![]() |
4593ece50f | ||
![]() |
cf8c13afa2 | ||
![]() |
7e5c750340 | ||
![]() |
e2c20840e4 | ||
![]() |
c7c53d8649 | ||
![]() |
1dcecbc281 | ||
![]() |
485e5cd088 | ||
![]() |
42dffc864d | ||
![]() |
abe52c831d | ||
![]() |
2322096927 | ||
![]() |
22c53316ab | ||
![]() |
e440f4b68a | ||
![]() |
e96d2a7a0b | ||
![]() |
e03dec6d91 | ||
![]() |
4ced2ea4d0 | ||
![]() |
924cfbeb95 | ||
![]() |
8266fcb633 | ||
![]() |
796098093b | ||
![]() |
8bd3efb1c4 | ||
![]() |
463130cdf8 | ||
![]() |
2d7fd864b3 | ||
![]() |
68a57b5ccc | ||
![]() |
63faf51685 | ||
![]() |
37cdba8ddd | ||
![]() |
9908084745 | ||
![]() |
1070f1f297 | ||
![]() |
f418bc47ab | ||
![]() |
29069012f7 | ||
![]() |
ce5d31e546 | ||
![]() |
d75e69841e | ||
![]() |
dfb773a96e | ||
![]() |
ba865715d7 | ||
![]() |
549657df21 | ||
![]() |
65306a30e8 | ||
![]() |
01e9524e7d | ||
![]() |
1664c48d7d | ||
![]() |
8524993e89 | ||
![]() |
87816a58e2 |
38 changed files with 1999 additions and 1519 deletions
|
@ -39,7 +39,7 @@ before_script:
|
|||
rustc --version
|
||||
cargo --version
|
||||
|
||||
# Check on stable, beta and nightly
|
||||
# Check on stable, beta and nightly
|
||||
.check-base: &check-base
|
||||
stage: check
|
||||
script:
|
||||
|
@ -64,16 +64,15 @@ check-nightly:
|
|||
<<: *check-base
|
||||
variables:
|
||||
RUST_VERSION: nightly
|
||||
check-old:
|
||||
check-msrv:
|
||||
<<: *check-base
|
||||
variables:
|
||||
RUST_VERSION: "1.40.0"
|
||||
RUST_VERSION: "1.63.0"
|
||||
|
||||
# Build using Rust stable
|
||||
build-x86_64-linux-gnu:
|
||||
stage: build
|
||||
needs:
|
||||
- check-stable
|
||||
needs: []
|
||||
script:
|
||||
- cargo build --target=$RUST_TARGET --release --verbose
|
||||
- mv target/$RUST_TARGET/release/ffsend ./ffsend-$RUST_TARGET
|
||||
|
@ -87,8 +86,7 @@ build-x86_64-linux-gnu:
|
|||
# Build a static version
|
||||
build-x86_64-linux-musl:
|
||||
stage: build
|
||||
needs:
|
||||
- check-stable
|
||||
needs: []
|
||||
variables:
|
||||
RUST_TARGET: x86_64-unknown-linux-musl
|
||||
script:
|
||||
|
@ -97,10 +95,10 @@ build-x86_64-linux-musl:
|
|||
|
||||
# Build OpenSSL statically
|
||||
- apt-get install -y build-essential wget musl-tools
|
||||
- wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2o.tar.gz
|
||||
- tar xzvf openssl-1.0.2o.tar.gz
|
||||
- cd openssl-1.0.2o
|
||||
- ./config -fPIC --openssldir=/usr/local/ssl --prefix=/usr/local
|
||||
- wget https://www.openssl.org/source/old/1.1.1/openssl-1.1.1k.tar.gz
|
||||
- tar xzvf openssl-1.1.1k.tar.gz
|
||||
- cd openssl-1.1.1k
|
||||
- ./config no-async -fPIC --openssldir=/usr/local/ssl --prefix=/usr/local
|
||||
- make
|
||||
- make install
|
||||
- cd ..
|
||||
|
@ -124,8 +122,7 @@ build-x86_64-linux-musl:
|
|||
# Run the unit tests through Cargo
|
||||
test-cargo:
|
||||
stage: test
|
||||
needs:
|
||||
- check-stable
|
||||
needs: []
|
||||
dependencies: []
|
||||
script:
|
||||
- cargo test --verbose
|
||||
|
@ -191,7 +188,7 @@ release-snap:
|
|||
# Publish snap package
|
||||
- echo "Publishing snap package..."
|
||||
- echo "$SNAPCRAFT_LOGIN" | base64 -d > snapcraft.login
|
||||
- snapcraft login --with snapcraft.login
|
||||
- snapcraft whoami
|
||||
- snapcraft push --release=stable ffsend_*_amd64.snap
|
||||
artifacts:
|
||||
name: ffsend-snap-x86_64
|
||||
|
@ -259,7 +256,7 @@ release-docker:
|
|||
|
||||
# AUR packages release
|
||||
package-aur:
|
||||
image: archlinux/base
|
||||
image: archlinux
|
||||
stage: package
|
||||
needs:
|
||||
- release-github
|
||||
|
@ -304,7 +301,7 @@ package-aur:
|
|||
- sed "s/^pkgver=.*\$/pkgver=$VERSION/" -i ffsend/PKGBUILD
|
||||
- sed "s/^pkgver=.*\$/pkgver=$VERSION/" -i ffsend-bin/PKGBUILD
|
||||
- sed "s/^pkgver=.*\$/pkgver=$VERSION.$CI_COMMIT_SHORT_SHA/" -i ffsend-git/PKGBUILD
|
||||
- sed "s/^source=(\"\(.*\)::.*\").*\$/source=(\"\1::$(echo $URL_SOURCE | sed 's/\//\\\//g')\")/" -i ffsend/PKGBUILD
|
||||
- sed "s/^source=(\".*\").*\$/source=(\"$(echo $URL_SOURCE | sed 's/\//\\\//g')\")/" -i ffsend/PKGBUILD
|
||||
- sed "s/\(\"ffsend-v\$pkgver::\).*\"/\1$(echo $URL_BIN | sed 's/\//\\\//g')\"/" -i ffsend-bin/PKGBUILD
|
||||
- sed "s/\(\"ffsend-v\$pkgver.bash::\).*\"/\1$(echo $URL_BASH_COMPLETION | sed 's/\//\\\//g')\"/" -i ffsend-bin/PKGBUILD
|
||||
- sed "s/\(\"ffsend-v\$pkgver.zsh::\).*\"/\1$(echo $URL_ZSH_COMPLETION | sed 's/\//\\\//g')\"/" -i ffsend-bin/PKGBUILD
|
||||
|
|
|
@ -18,7 +18,7 @@ Contributions to the `ffsend` project are welcome!
|
|||
When contributing new features, alternative implementations or bigger
|
||||
improvements, please first discuss the change you wish to make via an issue
|
||||
or email.
|
||||
Small changes such as fixed commands, fixed spelling or dependency updates
|
||||
Small changes such as fixed commands, fixed spelling or dependency updates
|
||||
are always welcome without discussion.
|
||||
|
||||
The `ffsend` repository is primarily hosted on [GitLab][gitlab].
|
||||
|
@ -115,11 +115,11 @@ members of the project's leadership.
|
|||
|
||||
### Attribution
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][coc-homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][coc-version]
|
||||
available at [https://contributor-covenant.org/version/1/4][coc-version]
|
||||
|
||||
## License
|
||||
This project is released under the GNU GPL-3.0 license.
|
||||
Check out the [LICENSE](LICENSE) file for more information.
|
||||
Check out the [LICENSE](LICENSE) file for more information.
|
||||
|
||||
[branch-master]: https://gitlab.com/timvisee/ffsend/tree/master
|
||||
[gitlab]: https://gitlab.com/timvisee/ffsend
|
||||
|
@ -128,5 +128,5 @@ Check out the [LICENSE](LICENSE) file for more information.
|
|||
[github]: https://github.com/timvisee/ffsend
|
||||
[github-issues]: https://github.com/timvisee/ffsend/issues
|
||||
[github-pr]: https://github.com/timvisee/ffsend/pulls
|
||||
[coc-homepage]: http://contributor-covenant.org
|
||||
[coc-version]: http://contributor-covenant.org/version/1/4/
|
||||
[coc-homepage]: https://contributor-covenant.org
|
||||
[coc-version]: https://contributor-covenant.org/version/1/4/
|
||||
|
|
2968
Cargo.lock
generated
2968
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
41
Cargo.toml
41
Cargo.toml
|
@ -1,6 +1,7 @@
|
|||
[package]
|
||||
name = "ffsend"
|
||||
version = "0.2.67"
|
||||
version = "0.2.76"
|
||||
rust-version = "1.63.0"
|
||||
authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
|
||||
license = "GPL-3.0"
|
||||
readme = "README.md"
|
||||
|
@ -8,7 +9,7 @@ homepage = "https://timvisee.com/projects/ffsend"
|
|||
repository = "https://gitlab.com/timvisee/ffsend"
|
||||
description = """\
|
||||
Easily and securely share files from the command line.\n\
|
||||
A fully featured Firefox Send client.\
|
||||
A fully featured Send client.\
|
||||
"""
|
||||
keywords = ["send", "firefox", "cli"]
|
||||
categories = [
|
||||
|
@ -49,24 +50,12 @@ license-file = ["LICENSE", "3"]
|
|||
depends = "$auto, libssl1.1, ca-certificates, xclip"
|
||||
maintainer-scripts = "pkg/deb"
|
||||
|
||||
[badges]
|
||||
gitlab = { repository = "timvisee/ffsend", branch = "master" }
|
||||
|
||||
[[bin]]
|
||||
name = "ffsend"
|
||||
path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = [
|
||||
"archive",
|
||||
"clipboard",
|
||||
"crypto-ring",
|
||||
"history",
|
||||
"infer-command",
|
||||
"qrcode",
|
||||
"send3",
|
||||
"urlshorten",
|
||||
]
|
||||
default = ["archive", "clipboard", "crypto-ring", "history", "infer-command", "qrcode", "send3", "urlshorten"]
|
||||
|
||||
# Compile with file archiving support
|
||||
archive = ["tar"]
|
||||
|
@ -77,10 +66,10 @@ clipboard = ["clip", "which"]
|
|||
# Compile with file history support
|
||||
history = []
|
||||
|
||||
# Support for Firefox Send v2
|
||||
# Support for Send v2
|
||||
send2 = ["ffsend-api/send2"]
|
||||
|
||||
# Support for Firefox Send v3
|
||||
# Support for Send v3
|
||||
send3 = ["ffsend-api/send3"]
|
||||
|
||||
# Use OpenSSL as cryptography backend
|
||||
|
@ -108,24 +97,24 @@ clipboard-bin = ["clipboard"]
|
|||
clipboard-crate = ["clipboard"]
|
||||
|
||||
[dependencies]
|
||||
chbs = "0.0.10"
|
||||
chbs = "0.1.0"
|
||||
chrono = "0.4"
|
||||
clap = "2.33"
|
||||
colored = "2.0"
|
||||
derive_builder = "0.9"
|
||||
directories = "3.0"
|
||||
derive_builder = "0.10"
|
||||
directories = "4.0"
|
||||
failure = "0.1"
|
||||
ffsend-api = { version = "0.6", default-features = false }
|
||||
ffsend-api = { version = "0.7.3", default-features = false }
|
||||
fs2 = "0.4"
|
||||
lazy_static = "1.4"
|
||||
open = "1"
|
||||
open = "2"
|
||||
openssl-probe = "0.1"
|
||||
pathdiff = "0.2"
|
||||
pbr = "1"
|
||||
prettytable-rs = "0.8"
|
||||
prettytable-rs = { version = "0.10.0", default-features = false }
|
||||
qr2term = { version = "0.2", optional = true }
|
||||
rand = "0.7"
|
||||
regex = "1.3"
|
||||
rand = "0.8"
|
||||
regex = "1.5"
|
||||
rpassword = "5"
|
||||
serde = "1"
|
||||
serde_derive = "1"
|
||||
|
@ -133,7 +122,7 @@ tar = { version = "0.4", optional = true }
|
|||
tempfile = "3"
|
||||
toml = "0.5"
|
||||
urlshortener = { version = "3", optional = true }
|
||||
version-compare = "0.0.11"
|
||||
version-compare = "0.1"
|
||||
|
||||
[target.'cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
|
||||
which = { version = "4.0", optional = true }
|
||||
|
|
8
LICENSE
8
LICENSE
|
@ -1,7 +1,7 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
|
74
README.md
74
README.md
|
@ -8,14 +8,14 @@
|
|||
[gitlab-ci-link]: https://gitlab.com/timvisee/ffsend/pipelines
|
||||
[gitlab-ci-master-badge]: https://gitlab.com/timvisee/ffsend/badges/master/pipeline.svg
|
||||
|
||||
*Notice: the default Send host is provided by [@timvisee][timvisee],
|
||||
[info](https://gitlab.com/timvisee/ffsend/-/issues/101).
|
||||
*Notice: the default Send host is provided by [@timvisee][timvisee]
|
||||
([info](https://gitlab.com/timvisee/ffsend/-/issues/111)).
|
||||
Please consider to [donate] and help keep it running.*
|
||||
|
||||
# ffsend
|
||||
|
||||
> Easily and securely share files from the command line.
|
||||
> [Firefox Send][send] client ([annonymous only][issue116] at the moment).
|
||||
> A [Send][send] client.
|
||||
|
||||
Easily and securely share files and directories from the command line through a
|
||||
safe, private and encrypted link using a single simple command.
|
||||
|
@ -45,9 +45,9 @@ Find out more about security [here](#security).
|
|||
- [License](#license)
|
||||
|
||||
The public [Send][send] service that is used as default host is provided by
|
||||
[@timvisee][timvisee].
|
||||
[@timvisee][timvisee] ([info](https://gitlab.com/timvisee/ffsend/-/issues/111)).
|
||||
This application is not affiliated with [Firefox][firefox] or
|
||||
[Firefox Send][send] in any way.
|
||||
[Mozilla][mozilla] in any way.
|
||||
|
||||
_Note: this tool is currently in beta, as some extra desired features are yet to be implemented_
|
||||
|
||||
|
@ -57,7 +57,7 @@ _Note: this tool is currently in beta, as some extra desired features are yet to
|
|||
- Additional password protection, generation and configurable download limits
|
||||
- File and directory archiving and extraction
|
||||
- Built-in share URL shortener and QR code generator
|
||||
- Supports Firefox Send v3 (current) and v2
|
||||
- Supports Send v3 (current) and v2
|
||||
- History tracking your files for easy management
|
||||
- Ability to use your own Send hosts
|
||||
- Inspect or delete shared files
|
||||
|
@ -74,7 +74,7 @@ Easily upload and download:
|
|||
```bash
|
||||
# Simple upload
|
||||
$ ffsend upload my-file.txt
|
||||
https://send.firefox.com/#sample-share-url
|
||||
https://send.vis.ee/#sample-share-url
|
||||
|
||||
# Advanced upload
|
||||
# - Specify a download limit of 1
|
||||
|
@ -85,25 +85,25 @@ https://send.firefox.com/#sample-share-url
|
|||
# - Open the shareable link in your browser
|
||||
$ ffsend upload --downloads 1 --expiry-time 5m --password --archive --copy --open my-file.txt
|
||||
Password: ******
|
||||
https://send.firefox.com/#sample-share-url
|
||||
https://send.vis.ee/#sample-share-url
|
||||
|
||||
# Upload to your own host
|
||||
$ ffsend u -h https://example.com/ my-file.txt
|
||||
https://example.com/#sample-share-url
|
||||
|
||||
# Simple download
|
||||
$ ffsend download https://send.firefox.com/#sample-share-url
|
||||
$ ffsend download https://send.vis.ee/#sample-share-url
|
||||
```
|
||||
|
||||
Inspect remote files:
|
||||
|
||||
```bash
|
||||
# Check if a file exists
|
||||
$ ffsend exists https://send.firefox.com/#sample-share-url
|
||||
$ ffsend exists https://send.vis.ee/#sample-share-url
|
||||
Exists: yes
|
||||
|
||||
# Fetch remote file info
|
||||
$ ffsend info https://send.firefox.com/#sample-share-url
|
||||
$ ffsend info https://send.vis.ee/#sample-share-url
|
||||
ID: b087066715
|
||||
Name: my-file.txt
|
||||
Size: 12 KiB
|
||||
|
@ -118,16 +118,16 @@ Other commands include:
|
|||
# View your file history
|
||||
$ ffsend history
|
||||
# LINK EXPIRE
|
||||
1 https://send.firefox.com/#sample-share-url 23h57m
|
||||
2 https://send.firefox.com/#other-sample-url 17h38m
|
||||
1 https://send.vis.ee/#sample-share-url 23h57m
|
||||
2 https://send.vis.ee/#other-sample-url 17h38m
|
||||
3 https://example.com/#sample-share-url 37m30s
|
||||
|
||||
# Change the password after uploading
|
||||
$ ffsend password https://send.firefox.com/#sample-share-url
|
||||
$ ffsend password https://send.vis.ee/#sample-share-url
|
||||
Password: ******
|
||||
|
||||
# Delete a file
|
||||
$ ffsend delete https://send.firefox.com/#sample-share-url
|
||||
$ ffsend delete https://send.vis.ee/#sample-share-url
|
||||
```
|
||||
|
||||
Use the `--help` flag, `help` subcommand, or see the [help](#help) section for
|
||||
|
@ -275,7 +275,7 @@ ffsend --help
|
|||
|
||||
### macOS
|
||||
Using the [`homebrew` package](#macos-homebrew-package) is recommended.
|
||||
Alternatively you may install it manually using the
|
||||
Alternatively you may install it via [MacPorts](#macos-macports), or manually using the
|
||||
[prebuilt binaries](#macos-prebuilt-binaries).
|
||||
|
||||
#### macOS: homebrew package
|
||||
|
@ -286,6 +286,17 @@ brew install ffsend
|
|||
ffsend --help
|
||||
```
|
||||
|
||||
#### macOS: MacPorts
|
||||
_Note: ffsend in MacPorts is currently not automatically updated, and might be
|
||||
slightly outdated._
|
||||
|
||||
Once you have [MacPorts](https://www.macports.org) installed, you can run:
|
||||
|
||||
```bash
|
||||
sudo port selfupdate
|
||||
sudo port install ffsend
|
||||
```
|
||||
|
||||
#### macOS: Nix package
|
||||
_Note: The Nix package is currently not automatically updated, and might be
|
||||
slightly outdated._
|
||||
|
@ -351,7 +362,7 @@ You can use `ffsend` from the command line in the same directory:
|
|||
.\ffsend.exe --help
|
||||
```
|
||||
|
||||
To make it globally invokable as `ffsend`, you must make the binary available in
|
||||
To make it globally invocable as `ffsend`, you must make the binary available in
|
||||
your systems `PATH`. The easiest solution is to move it into `System32`:
|
||||
```cmd
|
||||
move .\ffsend.exe C:\Windows\System32\ffsend.exe
|
||||
|
@ -407,7 +418,7 @@ docker run --rm -it -v $(pwd):/data timvisee/ffsend
|
|||
docker run --rm -it -v $(pwd):/data timvisee/ffsend upload my-file.txt
|
||||
|
||||
# Download from specified link
|
||||
docker run --rm -it -v $(pwd):/data timvisee/ffsend download https://send.firefox.com/#sample-share-url
|
||||
docker run --rm -it -v $(pwd):/data timvisee/ffsend download https://send.vis.ee/#sample-share-url
|
||||
|
||||
# Show help
|
||||
docker run --rm -it -v $(pwd):/data timvisee/ffsend help
|
||||
|
@ -417,7 +428,7 @@ docker pull timvisee/ffsend
|
|||
```
|
||||
|
||||
On Linux or macOS you might define a alias in your shell configuration, to make
|
||||
it invokable as `ffsend`:
|
||||
it invocable as `ffsend`:
|
||||
|
||||
```bash
|
||||
alias ffsend='docker run --rm -it -v "$(pwd):/data" timvisee/ffsend'
|
||||
|
@ -433,7 +444,7 @@ before proceeding:
|
|||
### Build requirements
|
||||
- Runtime [requirements](#requirements)
|
||||
- [`git`][git]
|
||||
- [`rust`][rust] `v1.40` or higher (install using [`rustup`][rustup])
|
||||
- [`rust`][rust] `v1.63` (MSRV) or higher (install using [`rustup`][rustup])
|
||||
- [OpenSSL][openssl] or [LibreSSL][libressl] libraries/headers:
|
||||
- Linux:
|
||||
- Ubuntu, Debian and derivatives: `apt install build-essential cmake pkg-config libssl-dev`
|
||||
|
@ -501,8 +512,8 @@ The following features are available, some of which are enabled by default:
|
|||
|
||||
| Feature | Enabled | Description |
|
||||
| :-------------: | :-----: | :--------------------------------------------------------- |
|
||||
| `send2` | Default | Support for Firefox Send v2 servers |
|
||||
| `send3` | Default | Support for Firefox Send v3 servers |
|
||||
| `send2` | Default | Support for Send v2 servers |
|
||||
| `send3` | Default | Support for Send v3 servers |
|
||||
| `crypto-ring` | Default | Use ring as cryptography backend |
|
||||
| `crypto-openssl`| | Use OpenSSL as cryptography backend |
|
||||
| `clipboard` | Default | Support for copying links to the clipboard |
|
||||
|
@ -545,6 +556,8 @@ to command line arguments:
|
|||
| `FFSEND_HOST` | `--host <URL>` | Upload host |
|
||||
| `FFSEND_TIMEOUT` | `--timeout <SECONDS>` | Request timeout (0 to disable) |
|
||||
| `FFSEND_TRANSFER_TIMEOUT` | `--transfer-timeout <SECONDS>` | Transfer timeout (0 to disable) |
|
||||
| `FFSEND_EXPIRY_TIME` | `--expiry-time <SECONDS>` | Default upload expiry time |
|
||||
| `FFSEND_DOWNLOAD_LIMIT` | `--download-limit <DOWNLOADS>` | Default download limit |
|
||||
| `FFSEND_API` | `--api <VERSION>` | Server API version, `-` to lookup |
|
||||
| `FFSEND_BASIC_AUTH` | `--basic-auth <USER:PASSWORD>` | Basic HTTP authentication credentials to use. |
|
||||
|
||||
|
@ -582,7 +595,7 @@ having `ffput` and `ffget` just for to upload and download using `ffsend`.
|
|||
This allows simple and direct commands like:
|
||||
```bash
|
||||
ffput my-file.txt
|
||||
ffget https://send.firefox.com/#sample-share-url
|
||||
ffget https://send.vis.ee/#sample-share-url
|
||||
```
|
||||
|
||||
This works for a predefined list of binary names:
|
||||
|
@ -731,10 +744,10 @@ documentation [here][send-encryption].
|
|||
```
|
||||
$ ffsend help
|
||||
|
||||
ffsend 0.2.67
|
||||
ffsend 0.2.72
|
||||
Tim Visee <3a4fb3964f@sinenomine.email>
|
||||
Easily and securely share files from the command line.
|
||||
A fully featured Firefox Send client.
|
||||
A fully featured Send client.
|
||||
|
||||
The default public Send host is provided by Tim Visee, @timvisee.
|
||||
Please consider to donate and help keep it running: https://vis.ee/donate
|
||||
|
@ -773,12 +786,12 @@ SUBCOMMANDS:
|
|||
password Change the password of a shared file [aliases: pass, p]
|
||||
version Determine the Send server version [aliases: v]
|
||||
|
||||
This application is not affiliated with Firefox or Firefox Send.
|
||||
This application is not affiliated with Firefox or Mozilla.
|
||||
```
|
||||
|
||||
## Special thanks
|
||||
- to all `ffsend` source/package contributors
|
||||
- to [Mozilla][mozilla] for building the amazing [Firefox Send][send] service
|
||||
- to [Mozilla][mozilla] for building the amazing [Firefox Send][mozilla-send] service ([fork][timvisee-send])
|
||||
- to everyone involved with [asciinema][asciinema] and [svg-term][svg-term] for
|
||||
providing tools to make great visual demos
|
||||
- to everyone involved in all crate dependencies used
|
||||
|
@ -798,8 +811,10 @@ Check out the [LICENSE](LICENSE) file for more information.
|
|||
[termux]: https://termux.com/
|
||||
[rust]: https://rust-lang.org/
|
||||
[rustup]: https://rustup.rs/
|
||||
[send]: https://send.firefox.com/
|
||||
[send-encryption]: https://github.com/mozilla/send/blob/master/docs/encryption.md
|
||||
[send]: https://github.com/timvisee/send
|
||||
[mozilla-send]: https://github.com/mozilla/send
|
||||
[timvisee-send]: https://github.com/timvisee/send
|
||||
[send-encryption]: https://github.com/timvisee/send/blob/master/docs/encryption.md
|
||||
[asciinema]: https://asciinema.org/
|
||||
[svg-term]: https://github.com/marionebl/svg-term-cli
|
||||
[github-releases]: https://github.com/timvisee/ffsend/releases
|
||||
|
@ -816,6 +831,5 @@ Check out the [LICENSE](LICENSE) file for more information.
|
|||
[docker-hub-ffsend]: https://hub.docker.com/r/timvisee/ffsend
|
||||
[scoop-install]: https://scoop.sh/#installs-in-seconds
|
||||
[freshports-ffsend]: https://www.freshports.org/www/ffsend
|
||||
[issue116]: https://github.com/timvisee/ffsend/issues/116
|
||||
[timvisee]: https://timvisee.com/
|
||||
[donate]: https://timvisee.com/donate
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
set -e
|
||||
|
||||
echo "Generating all completions using cargo debug binary..."
|
||||
cargo run -q -- generate completions all --output $PWD
|
||||
cargo run -q -- generate completions all --output "$PWD"
|
||||
echo "Done."
|
||||
|
|
6
contrib/util/nautilus/README.md
Normal file
6
contrib/util/nautilus/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
`firefox-send` is a script for Nautilus/Nemo/Caja (maybe it needs some adaptation for Caja) to send files directly from the file browser, using the contextual menu.
|
||||
|
||||
* Copy the `firefox-send` file to ~/.local/share/nautilus/scripts/firefox-send
|
||||
* Modify the default options to your use case: host server, download number, retention time.
|
||||
* Make the file executable (`chmod +x firefox-send`).
|
||||
* Restart Nautilus/Nemo/Caja.
|
46
contrib/util/nautilus/firefox-send
Executable file
46
contrib/util/nautilus/firefox-send
Executable file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
|
||||
#CONSTANTS
|
||||
#FILEPATH=`echo $NAUTILUS_SCRIPT_SELECTED_URIS | sed 's@file://@@g'`
|
||||
# Quote the paths
|
||||
IFS=$'\n' read -d '' -r -a FILEPATH <<< "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"
|
||||
FFSEND_BIN='/usr/bin/ffsend'
|
||||
FFSEND_BIN_OPTS="upload --open --copy"
|
||||
ZENITY='/usr/bin/zenity '
|
||||
ZENITY_PROGRESS_OPTIONS='--auto-close --auto-kill' #you can remove this if you like
|
||||
|
||||
#sanity checks
|
||||
for sanity_check in $FFSEND_BIN "${FILEPATH[@]}"
|
||||
do
|
||||
ZENITY_ERROR_SANITY="There is an error, it involved $sanity_check.\n Probably binary or file missing"
|
||||
if [ ! -e $sanity_check ]
|
||||
then
|
||||
#zenity --error --text="$(eval "echo \"$ZENITY_ERROR_SANITY\"")"
|
||||
zenity --error --text="$ZENITY_ERROR_SANITY"
|
||||
exit
|
||||
fi
|
||||
done
|
||||
|
||||
# Use the following flags automatically from now on
|
||||
# -I: no interaction
|
||||
# -f: force
|
||||
# -y: yes
|
||||
# -q: quiet
|
||||
export FFSEND_NO_INTERACT=1 FFSEND_FORCE=1 FFSEND_YES=1 FFSEND_QUIET=1
|
||||
export FFSEND_HOST=https://send.boblorange.net
|
||||
export FFSEND_EXPIRY_TIME=604800
|
||||
export FFSEND_DOWNLOAD_LIMIT=5
|
||||
|
||||
#check whether copying file or directory
|
||||
if [ ! -f "${FILEPATH[@]}" ]; then
|
||||
FFSEND_BIN_OPTS="$FFSEND_BIN_OPTS --archive"
|
||||
fi
|
||||
|
||||
# Upload a file
|
||||
#zenity --info --text="Ready to send: $FFSEND_BIN $FFSEND_BIN_OPTS ${FILEPATH[@]}"
|
||||
$FFSEND_BIN $FFSEND_BIN_OPTS "${FILEPATH[@]}" | $($ZENITY --progress --text="sending $(basename $FILEPATH)" --pulsate $ZENITY_PROGRESS_OPTIONS)
|
||||
#echo -e "$FILEPATH" | xargs -i $FFSEND_BIN $FFSEND_BIN_OPTS {} | $($ZENITY --progress --text="sending $(basename $FILEPATH)" --pulsate $ZENITY_PROGRESS_OPTIONS)
|
||||
|
||||
# Upload a file
|
||||
#echo -e "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" | xargs -i ffsend upload --open --copy {}
|
|
@ -3,7 +3,7 @@
|
|||
pkgname=ffsend
|
||||
pkgver=0.2.62
|
||||
pkgrel=0
|
||||
pkgdesc=" A fully featured Firefox Send client"
|
||||
pkgdesc=" A fully featured Send client"
|
||||
url="https://gitlab.com/timvisee/ffsend"
|
||||
arch="x86_64 x86 armhf armv7 aarch64 ppc64le" # limited by cargo
|
||||
license="GPL-3.0-only"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
pkgname=ffsend-bin
|
||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||
pkgrel=1
|
||||
pkgdesc="Easily and securely share files from the command line. A Firefox Send client."
|
||||
pkgdesc="Easily and securely share files from the command line. A Send client."
|
||||
url="https://gitlab.com/timvisee/ffsend"
|
||||
license=('GPL3')
|
||||
source=("ffsend-v$pkgver::https://github.com/timvisee/ffsend/releases/download/v$pkgver/ffsend-v$pkgver-linux-x64-static"
|
||||
|
@ -27,10 +27,9 @@ optdepends=('xclip: clipboard support'
|
|||
package() {
|
||||
cd "$srcdir"
|
||||
|
||||
# Install Binary
|
||||
install -Dm755 "ffsend-v$pkgver" "$pkgdir/usr/bin/ffsend"
|
||||
|
||||
# Install shell completions and LICENSE file
|
||||
# Shell completions and LICENSE file
|
||||
install -Dm644 "ffsend-v$pkgver.bash" "$pkgdir/usr/share/bash-completion/completions/ffsend"
|
||||
install -Dm644 "ffsend-v$pkgver.zsh" "$pkgdir/usr/share/zsh/site-functions/_ffsend"
|
||||
install -Dm644 "ffsend-v$pkgver.fish" "$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish"
|
||||
|
|
|
@ -7,31 +7,45 @@
|
|||
pkgname=ffsend-git
|
||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||
pkgrel=1
|
||||
pkgdesc="Easily and securely share files from the command line. A Firefox Send client."
|
||||
pkgdesc="Easily and securely share files from the command line. A Send client."
|
||||
url="https://gitlab.com/timvisee/ffsend"
|
||||
license=('GPL3')
|
||||
source=("ffsend::git+$url.git")
|
||||
source=("git+${url}")
|
||||
sha256sums=('SKIP')
|
||||
arch=('x86_64' 'i686')
|
||||
provides=('ffsend')
|
||||
conflicts=('ffsend')
|
||||
depends=('ca-certificates')
|
||||
makedepends=('openssl>=1.0' 'rust>=1.39' 'cargo' 'cmake')
|
||||
optdepends=('xclip: clipboard support'
|
||||
'bash-completion: support auto completion for bash')
|
||||
makedepends=('cargo' 'cmake' 'openssl>=1.0')
|
||||
optdepends=('xclip: clipboard support')
|
||||
|
||||
prepare() {
|
||||
cd "${pkgname%-git}"
|
||||
|
||||
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
||||
}
|
||||
|
||||
build() {
|
||||
cd ffsend
|
||||
env CARGO_INCREMENTAL=0 cargo build --release
|
||||
cd "${pkgname%-git}"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
export CARGO_TARGET_DIR=target
|
||||
cargo build --frozen --release
|
||||
}
|
||||
|
||||
check() {
|
||||
cd "${pkgname%-git}"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
cargo test --frozen
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/ffsend"
|
||||
cd "${pkgname%-git}"
|
||||
|
||||
# Install Binary
|
||||
install -Dm755 "./target/release/ffsend" "$pkgdir/usr/bin/ffsend"
|
||||
install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/ffsend"
|
||||
|
||||
# Install shell completions and LICENSE file
|
||||
# Shell completions and LICENSE file
|
||||
install -Dm644 "contrib/completions/ffsend.bash" \
|
||||
"$pkgdir/etc/bash_completion.d/ffsend"
|
||||
install -Dm644 "contrib/completions/_ffsend" \
|
||||
|
|
|
@ -7,30 +7,43 @@
|
|||
pkgname=ffsend
|
||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||
pkgrel=1
|
||||
pkgdesc="Easily and securely share files from the command line. A Firefox Send client."
|
||||
pkgdesc="Easily and securely share files from the command line. A Send client."
|
||||
url="https://gitlab.com/timvisee/ffsend"
|
||||
license=('GPL3')
|
||||
source=("ffsend-v$pkgver.tar.gz::$url/-/archive/v$pkgver/ffsend-v$pkgver.tar.gz") # automatically set in CI, see: /.gitlab-ci.yml
|
||||
source=("$url/-/archive/v$pkgver/ffsend-v$pkgver.tar.gz") # automatically set in CI, see: /.gitlab-ci.yml
|
||||
sha256sums=('SKIP') # automatically set in CI, see: /.gitlab-ci.yml
|
||||
arch=('x86_64' 'i686')
|
||||
provides=('ffsend')
|
||||
depends=('ca-certificates')
|
||||
makedepends=('openssl>=1.0' 'rust>=1.39' 'cargo' 'cmake')
|
||||
optdepends=('xclip: clipboard support'
|
||||
'bash-completion: support auto completion for bash')
|
||||
makedepends=('cargo' 'cmake' 'openssl>=1.0')
|
||||
optdepends=('xclip: clipboard support')
|
||||
|
||||
prepare() {
|
||||
cd "$pkgname-v$pkgver"
|
||||
|
||||
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
||||
}
|
||||
|
||||
build() {
|
||||
cd "ffsend-v$pkgver"
|
||||
env CARGO_INCREMENTAL=0 cargo build --release
|
||||
cd "$pkgname-v$pkgver"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
export CARGO_TARGET_DIR=target
|
||||
cargo build --frozen --release
|
||||
}
|
||||
|
||||
check() {
|
||||
cd "$pkgname-v$pkgver"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=stable
|
||||
cargo test --frozen
|
||||
}
|
||||
|
||||
package() {
|
||||
cd "$srcdir/ffsend-v$pkgver"
|
||||
cd "$pkgname-v$pkgver"
|
||||
|
||||
# Install Binary
|
||||
install -Dm755 "./target/release/ffsend" "$pkgdir/usr/bin/ffsend"
|
||||
install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
|
||||
|
||||
# Install shell completions and LICENSE file
|
||||
# Shell completions and LICENSE file
|
||||
install -Dm644 "contrib/completions/ffsend.bash" \
|
||||
"$pkgdir/etc/bash_completion.d/ffsend"
|
||||
install -Dm644 "contrib/completions/_ffsend" \
|
||||
|
|
|
@ -45,8 +45,8 @@ This is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Refe
|
|||
<docsUrl>https://github.com/timvisee/ffsend</docsUrl>
|
||||
<bugTrackerUrl>https://gitlab.com/timvisee/ffsend/issues</bugTrackerUrl>
|
||||
<tags>ffsend firefox-send cli file-sharing file-upload encryption rust</tags>
|
||||
<summary>Easily and securely share files from the command line. A fully featured Firefox Send client.</summary>
|
||||
<description>Easily and securely share files from the command line. A fully featured Firefox Send client.</description>
|
||||
<summary>Easily and securely share files from the command line. A fully featured Send client.</summary>
|
||||
<description>Easily and securely share files from the command line. A fully featured Send client.</description>
|
||||
<!-- =============================== -->
|
||||
|
||||
<!-- Specifying dependencies and version ranges? https://docs.nuget.org/create/versioning#specifying-version-ranges-in-.nuspec-files -->
|
||||
|
|
|
@ -9,13 +9,13 @@ if [[ ! $TRAVIS_TAG =~ ^v([0-9]+\.)*[0-9]+$ ]]; then
|
|||
fi
|
||||
|
||||
# Ensure the debian architecture is set
|
||||
if [[ -z "$DEB_ARCH" ]]; then
|
||||
if [[ -z $DEB_ARCH ]]; then
|
||||
echo "Error: debian architecture not configured in \$DEB_ARCH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Define some useful variables
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
VERSION=${TRAVIS_TAG:1}
|
||||
|
||||
# Ensure the binary file exists
|
||||
|
@ -25,23 +25,23 @@ if [[ ! -f "$DIR/../ffsend" ]]; then
|
|||
fi
|
||||
|
||||
# Create an application directory, copy the binary into it
|
||||
mkdir -p $DIR/ffsend-$VERSION
|
||||
cp $DIR/../ffsend $DIR/ffsend-$VERSION/ffsend
|
||||
mkdir -p "$DIR/ffsend-$VERSION"
|
||||
cp -- "$DIR/../ffsend" "$DIR/ffsend-$VERSION/ffsend"
|
||||
|
||||
# Create an application tarbal
|
||||
cd $DIR/..
|
||||
git archive --format tar.gz -o $DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz $TRAVIS_TAG
|
||||
# Create an application tarball
|
||||
cd -- "$DIR/.."
|
||||
git archive --format tar.gz -o "$DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz" "$TRAVIS_TAG"
|
||||
|
||||
# Change into the app directory
|
||||
cd $DIR/ffsend-$VERSION
|
||||
cd -- "$DIR/ffsend-$VERSION"
|
||||
|
||||
# Build the debian package
|
||||
# TODO: define GPG?
|
||||
dh_make -e "timvisee@gmail.com" -c gpl3 -f ffsend-$VERSION.tar.gz -s -y
|
||||
rm *.ex README.Debian README.source
|
||||
dh_make -e "timvisee@gmail.com" -c gpl3 -f "ffsend-$VERSION.tar.gz" -s -y
|
||||
rm -- *.ex README.Debian README.source
|
||||
|
||||
# Remove the project tar ball, we're not using it anymore
|
||||
rm $DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz
|
||||
rm -- "$DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz"
|
||||
|
||||
# TODO: configure the debian/control file
|
||||
# TODO: configure copyright file
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
# Unlink the ffs alias if it links to ffsend
|
||||
if [[ -L /usr/bin/ffs ]] \
|
||||
&& [[ $(ls -l /usr/bin/ffs | sed -e 's/.* -> //') == "/usr/bin/ffsend" ]]; \
|
||||
&& [[ $(realpath /usr/bin/ffs) == "/usr/bin/ffsend" ]]; \
|
||||
then
|
||||
echo "Removing ffs alias for ffsend..."
|
||||
unlink /usr/bin/ffs
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"homepage": "https://github.com/timvisee/ffsend",
|
||||
"description": "Easily and securely share files from the command line. A fully featured Firefox Send client.",
|
||||
"description": "Easily and securely share files from the command line. A fully featured Send client.",
|
||||
"license": "GPL-3.0-only",
|
||||
"version": "0.0.0",
|
||||
"architecture": {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Ensure svg-term is installed
|
||||
if ! [ -x "$(command -v svg-term)" ]; then
|
||||
|
|
1
snapcraft.login
Normal file
1
snapcraft.login
Normal file
|
@ -0,0 +1 @@
|
|||
eyJyIjogIk1EQXlPV3h2WTJGMGFXOXVJRzE1WVhCd2N5NWtaWFpsYkc5d1pYSXVkV0oxYm5SMUxtTnZiUW93TURFMmFXUmxiblJwWm1sbGNpQk5lVUZ3Y0hNS01EQTBZbU5wWkNCdGVXRndjSE11WkdWMlpXeHZjR1Z5TG5WaWRXNTBkUzVqYjIxOGRtRnNhV1JmYzJsdVkyVjhNakF5TWkwd05pMHlNRlF3T0Rvd016b3hNaTQwTlRreU9EUUtNREUzWkdOcFpDQjdJblpsY25OcGIyNGlPaUF4TENBaWMyVmpjbVYwSWpvZ0ltOWFVRzlpVG1vdlJYTmhkazlYUVZoRmNIQlRNM1JNY0RGak1tdFZaVU5NYzFaWlNUQmFaa1JFZERkcVozaHhTVlI2VEhselFtOVZjV3N5VURad1JXdFFRblpNUkhOMFkwTTNSRlU1VUVFMGFXVlpPV0U0WWxGU2VtNHJNbTQxVEVsRWMwY3ZTVEphVEM4eU1uSTBjakZDYmlzM1VqRnhUVWt2WjNoR1kzVnVVV05pUlZkeVVWQXdZV3BrUTBrd1pWRmxOVEZsVmpWSVJrbzNjMlZGU0c5WVpFRlZTVVZ1Vm1GNU5sRnFVMDQzTW1SSFpWSlVabVZvYVVacmFWbFFaVVJJZVN0d1VqbHVjMXBNZW5aMFNYbHNPRnBYYVhkSVdIcFpRVTl2T0Rob1VXdFhZakZ6UzNGSGFYWjZWRFZEWlZoV1IyaElaalJSUVdRNVIwOWxLMjUxUmpWM2JHMWtaRlIwY1U1YWNWQnNjVkZHYjBoelprUk9jRFpvVFd4dWFHbDVMMGxvY2tOclZscENUVzFMYld0cFIwVk1VWFZMTUVSUVFtdFFNSE5RVWpaVVdsWnFjVGQzZVRaaFdIa3dVM1ZyZDBaclp6MDlJbjBLTURBMU1YWnBaQ0ExYU5mbjFKU3NBa1VoMFM1NXB4bnp2VUxESlRtcldMLTZSa3B0c3kzbFdVSG02T0hVQnJHeGtfYmlnbnEtbkxIMm9hYVdwaENKRkM1YzNod1BqWjBXUl83bUZ5QWN2QlFLTURBeE9HTnNJR3h2WjJsdUxuVmlkVzUwZFM1amIyMEtNREJoT1dOcFpDQnRlV0Z3Y0hNdVpHVjJaV3h2Y0dWeUxuVmlkVzUwZFM1amIyMThZV05zZkZzaWNHRmphMkZuWlY5aFkyTmxjM01pTENBaWNHRmphMkZuWlY5dFlXNWhaMlVpTENBaWNHRmphMkZuWlY5dFpYUnlhV056SWl3Z0luQmhZMnRoWjJWZmNIVnphQ0lzSUNKd1lXTnJZV2RsWDNKbFoybHpkR1Z5SWl3Z0luQmhZMnRoWjJWZmNtVnNaV0Z6WlNJc0lDSndZV05yWVdkbFgzVndaR0YwWlNKZENqQXdORGRqYVdRZ2JYbGhjSEJ6TG1SbGRtVnNiM0JsY2k1MVluVnVkSFV1WTI5dGZHVjRjR2x5WlhOOE1qQXlNeTB3TmkweU1GUXdPRG93TXpveE1pNHdNREF3TVRjS01EQXlabk5wWjI1aGRIVnlaU0JOYm05MFAyTkpYV3RON0I1aktWbkVBQUZqM0c3dzItLWNhOGloR2lJWUhRbyIsICJkIjogIk1EQXhaV3h2WTJGMGFXOXVJR3h2WjJsdUxuVmlkVzUwZFM1amIyMEtNREU0Tkdsa1pXNTBhV1pwWlhJZ2V5SjJaWEp6YVc5dUlqb2dNU3dnSW5ObFkzSmxkQ0k2SUNKdldsQnZZazVxTDBWellYWlBWMEZZUlhCd1V6TjBUSEF4WXpKclZXVkRUSE5XV1Vrd1dtWkVSSFEzYW1kNGNVbFVla3g1YzBKdlZYRnJNbEEyY0VWclVFSjJURVJ6ZEdORE4wUlZPVkJCTkdsbFdUbGhPR0pSVW5wdUt6SnVOVXhKUkhOSEwwa3lXa3d2TWpKeU5ISXhRbTRyTjFJeGNVMUpMMmQ0Um1OMWJsRmpZa1ZYY2xGUU1HRnFaRU5KTUdWUlpUVXhaVlkxU0VaS04zTmxSVWh2V0dSQlZVbEZibFpoZVRaUmFsTk9OekprUjJWU1ZHWmxhR2xHYTJsWlVHVkVTSGtyY0ZJNWJuTmFUSHAyZEVsNWJEaGFWMmwzU0ZoNldVRlBiemc0YUZGclYySXhjMHR4UjJsMmVsUTFRMlZZVmtkb1NHWTBVVUZrT1VkUFpTdHVkVVkxZDJ4dFpHUlVkSEZPV25GUWJIRlJSbTlJYzJaRVRuQTJhRTFzYm1ocGVTOUphSEpEYTFaYVFrMXRTMjFyYVVkRlRGRjFTekJFVUVKclVEQnpVRkkyVkZwV2FuRTNkM2syWVZoNU1GTjFhM2RHYTJjOVBTSjlDakF3WkRaamFXUWdiRzluYVc0dWRXSjFiblIxTG1OdmJYeGhZMk52ZFc1MGZHVjVTakZqTWxaNVltMUdkRnBUU1RaSlEwb3dZVmN4TW1GWVRteGFVMGx6U1VOS2RtTkhWblZoVjFGcFQybEJhVlZ1WkV4UlZXaDBVME5KYzBsRFNtdGhXRTUzWWtkR05XSnRSblJhVTBrMlNVTktWV0ZYTUdkV2JXeDZXRWhWZDAxSFZUVmFVMGx6U1VOS2JHSlhSbkJpUTBrMlNVTktNR0ZYTUhKa1Ywb3hZbTVTTVdJeU5XeFJTRnB3WXpKV2JFeHRNV3hKYVhkblNXMXNlbGd6V214amJXeHRZVmRXYTBscWIyZGtTRW94V2xnd1BRb3dNRFF3WTJsa0lHeHZaMmx1TG5WaWRXNTBkUzVqYjIxOGRtRnNhV1JmYzJsdVkyVjhNakF5TWkwd05pMHlNRlF3T0Rvd016b3hNeTR5T0RJd09UTUtNREF6WldOcFpDQnNiMmRwYmk1MVluVnVkSFV1WTI5dGZHeGhjM1JmWVhWMGFId3lNREl5TFRBMkxUSXdWREE0T2pBek9qRXpMakk0TWpBNU13b3dNREptYzJsbmJtRjBkWEpsSVBtdzV2aGZjWXhjRVFzX1RHV2VHWUFrQWhxdkJONVJjOFpHTEpnVFZ2eGxDZyJ9
|
|
@ -139,7 +139,7 @@ impl<'a> Download<'a> {
|
|||
{
|
||||
// Allocate an archive file, and update the download and target paths
|
||||
if extract {
|
||||
// TODO: select the extention dynamically
|
||||
// TODO: select the extension dynamically
|
||||
let archive_extention = ".tar";
|
||||
|
||||
// Allocate a temporary file to download the archive to
|
||||
|
@ -210,7 +210,7 @@ impl<'a> Download<'a> {
|
|||
///
|
||||
/// The full path including the name is returned.
|
||||
///
|
||||
/// This method will check whether a file is overwitten, and whether
|
||||
/// This method will check whether a file is overwritten, and whether
|
||||
/// parent directories must be created.
|
||||
///
|
||||
/// The program will quit with an error message if a problem occurs.
|
||||
|
@ -313,7 +313,7 @@ impl<'a> Download<'a> {
|
|||
// Get the path string
|
||||
let path = target.to_str();
|
||||
|
||||
// If the path is emtpy, use the working directory with the name hint
|
||||
// If the path is empty, use the working directory with the name hint
|
||||
let use_workdir = path.map(|path| path.trim().is_empty()).unwrap_or(true);
|
||||
if use_workdir {
|
||||
match current_dir() {
|
||||
|
|
|
@ -24,7 +24,7 @@ impl<'a> Completions<'a> {
|
|||
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
||||
let matcher_completions = CompletionsMatcher::with(self.cmd_matches).unwrap();
|
||||
|
||||
// Obtian shells to generate completions for, build application definition
|
||||
// Obtain shells to generate completions for, build application definition
|
||||
let shells = matcher_completions.shells();
|
||||
let dir = matcher_completions.output();
|
||||
let quiet = matcher_main.quiet();
|
||||
|
@ -38,14 +38,14 @@ impl<'a> Completions<'a> {
|
|||
// Generate completions
|
||||
for shell in shells {
|
||||
if !quiet {
|
||||
print!(
|
||||
eprint!(
|
||||
"Generating completions for {}...",
|
||||
format!("{}", shell).to_lowercase()
|
||||
);
|
||||
}
|
||||
app.gen_completions(crate_name!(), shell, &dir);
|
||||
if !quiet {
|
||||
println!(" done.");
|
||||
eprintln!(" done.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ impl<'a> History<'a> {
|
|||
|
||||
// Remove history item
|
||||
if let Some(url) = matcher_history.rm() {
|
||||
// Remove item, print error if no item with URL was foudn
|
||||
// Remove item, print error if no item with URL was found
|
||||
match history.remove_url(url) {
|
||||
Ok(removed) if !removed => quit_error_msg(
|
||||
"could not remove item from history, no item matches given URL",
|
||||
|
@ -120,11 +120,8 @@ impl<'a> History<'a> {
|
|||
};
|
||||
|
||||
// Define the cell values
|
||||
let mut cells: Vec<String> = vec![
|
||||
format!("{}", i + 1),
|
||||
file.download_url(true).into_string(),
|
||||
expiry,
|
||||
];
|
||||
let mut cells: Vec<String> =
|
||||
vec![format!("{}", i + 1), file.download_url(true).into(), expiry];
|
||||
if matcher_main.verbose() {
|
||||
cells.push(owner_token);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ fn select_api_version(
|
|||
));
|
||||
}
|
||||
|
||||
// Propegate other errors
|
||||
// Propagate other errors
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::env::current_dir;
|
||||
use std::fs;
|
||||
use std::io::Error as IoError;
|
||||
use std::io::{Error as IoError, Write};
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "archive")]
|
||||
use std::path::PathBuf;
|
||||
|
@ -19,7 +19,6 @@ use pathdiff::diff_paths;
|
|||
use prettytable::{format::FormatBuilder, Cell, Row, Table};
|
||||
#[cfg(feature = "qrcode")]
|
||||
use qr2term::print_qr;
|
||||
#[cfg(feature = "archive")]
|
||||
use tempfile::{Builder as TempBuilder, NamedTempFile};
|
||||
|
||||
use super::select_api_version;
|
||||
|
@ -36,7 +35,7 @@ use crate::urlshorten;
|
|||
use crate::util::set_clipboard;
|
||||
use crate::util::{
|
||||
format_bytes, open_url, print_error, print_error_msg, prompt_yes, quit, quit_error_msg,
|
||||
rand_alphanum_string, ErrorHintsBuilder,
|
||||
rand_alphanum_string, stdin_read_file, ErrorHintsBuilder, StdinErr,
|
||||
};
|
||||
|
||||
/// A file upload action.
|
||||
|
@ -57,20 +56,49 @@ impl<'a> Upload<'a> {
|
|||
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
||||
let matcher_upload = UploadMatcher::with(self.cmd_matches).unwrap();
|
||||
|
||||
// The file name to use
|
||||
#[allow(unused_mut)]
|
||||
let mut file_name = matcher_upload.name().map(|s| s.to_owned());
|
||||
|
||||
// The selected files
|
||||
let mut files = matcher_upload.files();
|
||||
|
||||
// If file is `-`, upload from stdin
|
||||
// TODO: write stdin directly to file, or directly to upload buffer
|
||||
let mut tmp_stdin: Option<NamedTempFile> = None;
|
||||
if files.len() == 1 && files[0] == "-" {
|
||||
// Obtain data from stdin
|
||||
let data = stdin_read_file(!matcher_main.quiet()).map_err(Error::Stdin)?;
|
||||
|
||||
// Create temporary stdin buffer file
|
||||
tmp_stdin = Some(
|
||||
TempBuilder::new()
|
||||
.prefix(&format!(".{}-stdin-", crate_name!()))
|
||||
.tempfile()
|
||||
.map_err(Error::StdinTempFile)?,
|
||||
);
|
||||
let file = tmp_stdin.as_ref().unwrap();
|
||||
|
||||
// Fill temporary file with data, update list of files we upload, suggest name
|
||||
file.as_file()
|
||||
.write_all(&data)
|
||||
.map_err(Error::StdinTempFile)?;
|
||||
files = vec![file
|
||||
.path()
|
||||
.to_str()
|
||||
.expect("failed to obtain file name for stdin buffer file")];
|
||||
file_name = file_name.or_else(|| Some("stdin.txt".into()));
|
||||
}
|
||||
|
||||
// Get API parameters
|
||||
#[allow(unused_mut)]
|
||||
let mut paths: Vec<_> = matcher_upload
|
||||
.files()
|
||||
let mut paths: Vec<_> = files
|
||||
.into_iter()
|
||||
.map(|p| Path::new(p).to_path_buf())
|
||||
.collect();
|
||||
let mut path = Path::new(paths.first().unwrap()).to_path_buf();
|
||||
let host = matcher_upload.host();
|
||||
|
||||
// The file name to use
|
||||
#[allow(unused_mut)]
|
||||
let mut file_name = matcher_upload.name().map(|s| s.to_owned());
|
||||
|
||||
// All paths must exist
|
||||
// TODO: ensure the file exists and is accessible
|
||||
for path in &paths {
|
||||
|
@ -196,7 +224,7 @@ impl<'a> Upload<'a> {
|
|||
// Finish the archival process, writes the archive file
|
||||
archiver.finish().map_err(ArchiveError::Write)?;
|
||||
|
||||
// Append archive extention to name, set to upload archived file
|
||||
// Append archive extension to name, set to upload archived file
|
||||
if let Some(ref mut file_name) = file_name {
|
||||
file_name.push_str(archive_extention);
|
||||
}
|
||||
|
@ -247,7 +275,7 @@ impl<'a> Upload<'a> {
|
|||
// TODO: set false parameter to authentication state
|
||||
let max_size = upload_size_max(api_version, auth);
|
||||
|
||||
// Get the file size, fail on emtpy files, warn about large files
|
||||
// Get the file size, fail on empty files, warn about large files
|
||||
if let Ok(size) = path.metadata().map(|m| m.len()) {
|
||||
// Enforce files not being 0 bytes
|
||||
if size == 0 && !matcher_main.force() {
|
||||
|
@ -289,7 +317,7 @@ impl<'a> Upload<'a> {
|
|||
|
||||
// Prompt the user to continue, quit if the user answered no
|
||||
if !prompt_yes("Continue uploading?", Some(true), &matcher_main) {
|
||||
println!("Upload cancelled");
|
||||
eprintln!("Upload cancelled");
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
@ -454,6 +482,16 @@ impl<'a> Upload<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Close the temporary stdin buffer file, to ensure it's removed
|
||||
if let Some(tmp_stdin) = tmp_stdin.take() {
|
||||
if let Err(err) = tmp_stdin.close() {
|
||||
print_error(
|
||||
err.context("failed to clean up temporary stdin buffer file, ignoring")
|
||||
.compat(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "archive")]
|
||||
{
|
||||
// Close the temporary zip file, to ensure it's removed
|
||||
|
@ -581,6 +619,14 @@ pub enum Error {
|
|||
/// An error occurred while deleting a local file after upload.
|
||||
#[fail(display = "failed to delete local file")]
|
||||
Delete(#[cause] IoError),
|
||||
|
||||
/// An error occurred while reading data from stdin.
|
||||
#[fail(display = "failed to read data from stdin")]
|
||||
Stdin(#[cause] StdinErr),
|
||||
|
||||
/// An error occurred while creating the temporary stdin file.
|
||||
#[fail(display = "failed to create temporary stdin buffer file")]
|
||||
StdinTempFile(#[cause] IoError),
|
||||
}
|
||||
|
||||
impl From<VersionError> for Error {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::io::{Error as IoError, Read};
|
||||
use std::path::Path;
|
||||
|
||||
use super::tar::Archive as TarArchive;
|
||||
use tar::Archive as TarArchive;
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, IoError>;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fs::File;
|
|||
use std::io::{Error as IoError, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use super::tar::Builder as TarBuilder;
|
||||
use tar::Builder as TarBuilder;
|
||||
|
||||
pub type Result<T> = ::std::result::Result<T, IoError>;
|
||||
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
extern crate tar;
|
||||
|
||||
pub mod archive;
|
||||
pub mod archiver;
|
||||
|
|
|
@ -24,7 +24,7 @@ impl CmdArg for ArgApi {
|
|||
.help("Server API version to use, '-' to lookup")
|
||||
.long_help(
|
||||
"Server API version to use, one of:\n\
|
||||
2, 3: Firefox Send API versions\n\
|
||||
2, 3: Send API versions\n\
|
||||
auto, -: probe server to determine\
|
||||
",
|
||||
)
|
||||
|
|
|
@ -68,6 +68,7 @@ impl CmdArg for ArgDownloadLimit {
|
|||
.alias("downloads")
|
||||
.alias("download")
|
||||
.value_name("COUNT")
|
||||
.env("FFSEND_DOWNLOAD_LIMIT")
|
||||
.help("The file download limit")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ impl CmdArg for ArgExpiryTime {
|
|||
.alias("expire")
|
||||
.alias("expiry")
|
||||
.value_name("TIME")
|
||||
.env("FFSEND_EXPIRY_TIME")
|
||||
.help("The file expiry time")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,16 @@
|
|||
use chbs::{config::BasicConfig, prelude::*, word::WordList};
|
||||
use chbs;
|
||||
use clap::Arg;
|
||||
|
||||
use super::{CmdArg, CmdArgFlag};
|
||||
|
||||
/// How many words the passphrase should consist of.
|
||||
const PASSPHRASE_WORDS: usize = 5;
|
||||
|
||||
/// The passphrase generation argument.
|
||||
pub struct ArgGenPassphrase {}
|
||||
|
||||
impl ArgGenPassphrase {
|
||||
/// Generate a cryptographically secure passphrase that is easily
|
||||
/// rememberable using diceware.
|
||||
/// remembered using diceware.
|
||||
pub fn gen_passphrase() -> String {
|
||||
let mut config = BasicConfig::default();
|
||||
config.words = PASSPHRASE_WORDS;
|
||||
config.word_provider = WordList::builtin_eff_general_short().sampler();
|
||||
config.to_scheme().generate()
|
||||
chbs::passphrase()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ pub mod owner;
|
|||
pub mod password;
|
||||
pub mod url;
|
||||
|
||||
// Re-eexport to arg module
|
||||
// Re-export to arg module
|
||||
pub use self::api::ArgApi;
|
||||
pub use self::basic_auth::ArgBasicAuth;
|
||||
pub use self::download_limit::ArgDownloadLimit;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
extern crate directories;
|
||||
|
||||
#[cfg(feature = "infer-command")]
|
||||
use std::ffi::OsString;
|
||||
|
||||
|
@ -64,7 +62,7 @@ impl<'a: 'b, 'b> Handler<'a> {
|
|||
.version(crate_version!())
|
||||
.author(crate_authors!())
|
||||
.about(APP_ABOUT.as_ref())
|
||||
.after_help("This application is not affiliated with Firefox or Firefox Send.")
|
||||
.after_help("This application is not affiliated with Firefox or Mozilla.")
|
||||
.global_setting(AppSettings::GlobalVersion)
|
||||
.global_setting(AppSettings::VersionlessSubcommands)
|
||||
// TODO: enable below command when it doesn't break `p` anymore.
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<'a: 'b, 'b> UploadMatcher<'a> {
|
|||
let name = self.matches.value_of("name")?;
|
||||
|
||||
// The file name must not be empty
|
||||
// TODO: allow to force an empty name here, and process emtpy names on downloading
|
||||
// TODO: allow to force an empty name here, and process empty names on downloading
|
||||
if name.trim().is_empty() {
|
||||
quit_error_msg(
|
||||
"the file name must not be empty",
|
||||
|
@ -171,7 +171,7 @@ pub enum CopyMode {
|
|||
}
|
||||
|
||||
impl CopyMode {
|
||||
/// Build the string to copy, based on the given `url` and currend mode.
|
||||
/// Build the string to copy, based on the given `url` and current mode.
|
||||
pub fn build(&self, url: &str) -> String {
|
||||
match self {
|
||||
CopyMode::Url => url.into(),
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
extern crate toml;
|
||||
extern crate version_compare;
|
||||
|
||||
use std::fs;
|
||||
use std::io::Error as IoError;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use self::toml::de::Error as DeError;
|
||||
use self::toml::ser::Error as SerError;
|
||||
use self::version_compare::{CompOp, VersionCompare};
|
||||
use failure::Fail;
|
||||
use ffsend_api::file::remote_file::{FileParseError, RemoteFile};
|
||||
use ffsend_api::url::Url;
|
||||
use ffsend_api::{
|
||||
file::remote_file::{FileParseError, RemoteFile},
|
||||
url::Url,
|
||||
};
|
||||
use toml::{de::Error as DeError, ser::Error as SerError};
|
||||
use version_compare::Cmp;
|
||||
|
||||
use crate::util::{print_error, print_warning};
|
||||
|
||||
|
@ -23,7 +21,7 @@ const VERSION_MAX: &str = crate_version!();
|
|||
#[derive(Serialize, Deserialize)]
|
||||
pub struct History {
|
||||
/// The application version the history file was built with.
|
||||
/// Used for compatability checking.
|
||||
/// Used for compatibility checking.
|
||||
version: Option<String>,
|
||||
|
||||
/// The file history.
|
||||
|
@ -64,9 +62,9 @@ impl History {
|
|||
// Get the version number from the file
|
||||
let version = history.version.as_ref().unwrap();
|
||||
|
||||
if let Ok(true) = VersionCompare::compare_to(version, VERSION_MIN, &CompOp::Lt) {
|
||||
if let Ok(true) = version_compare::compare_to(version, VERSION_MIN, Cmp::Lt) {
|
||||
print_warning("history file version is too old, ignoring");
|
||||
} else if let Ok(true) = VersionCompare::compare_to(version, VERSION_MAX, &CompOp::Gt) {
|
||||
} else if let Ok(true) = version_compare::compare_to(version, VERSION_MAX, Cmp::Gt) {
|
||||
print_warning("history file has an unknown version, ignoring");
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +224,7 @@ impl History {
|
|||
///
|
||||
/// If the expiry property is None (thus unknown), the file will be kept.
|
||||
///
|
||||
/// The number of exired files is returned.
|
||||
/// The number of expired files is returned.
|
||||
pub fn gc(&mut self) -> usize {
|
||||
// Get a list of expired files
|
||||
let expired: Vec<RemoteFile> = self
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
extern crate pbr;
|
||||
|
||||
use std::io::{stderr, Stderr};
|
||||
use std::time::Duration;
|
||||
|
||||
use self::pbr::{ProgressBar as Pbr, Units};
|
||||
use ffsend_api::pipe::ProgressReporter;
|
||||
use pbr::{ProgressBar as Pbr, Units};
|
||||
|
||||
/// The refresh rate of the progress bar, in milliseconds.
|
||||
const PROGRESS_BAR_FPS_MILLIS: u64 = 200;
|
||||
|
|
|
@ -76,7 +76,7 @@ pub enum Error {
|
|||
#[fail(display = "failed to shorten URL, got bad response")]
|
||||
Response(#[cause] ResponseError),
|
||||
|
||||
/// The server resonded with a malformed repsonse.
|
||||
/// The server responded with a malformed response.
|
||||
#[fail(display = "failed to shorten URL, got malformed response")]
|
||||
Malformed(#[cause] reqwest::Error),
|
||||
|
||||
|
|
68
src/util.rs
68
src/util.rs
|
@ -1,10 +1,5 @@
|
|||
#[cfg(feature = "clipboard-crate")]
|
||||
extern crate clip;
|
||||
extern crate colored;
|
||||
extern crate directories;
|
||||
extern crate fs2;
|
||||
extern crate open;
|
||||
extern crate regex;
|
||||
#[cfg(feature = "clipboard-bin")]
|
||||
extern crate which;
|
||||
|
||||
|
@ -16,21 +11,21 @@ use std::fmt;
|
|||
use std::fmt::{Debug, Display};
|
||||
#[cfg(feature = "clipboard-bin")]
|
||||
use std::io::ErrorKind as IoErrorKind;
|
||||
use std::io::{self, Read};
|
||||
use std::io::{stderr, stdin, Error as IoError, Write};
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{exit, ExitStatus};
|
||||
use std::process::exit;
|
||||
#[cfg(feature = "clipboard-bin")]
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
#[cfg(feature = "clipboard-crate")]
|
||||
use self::clip::{ClipboardContext, ClipboardProvider};
|
||||
use self::colored::*;
|
||||
#[cfg(feature = "history")]
|
||||
use self::directories::ProjectDirs;
|
||||
use self::fs2::available_space;
|
||||
use chrono::Duration;
|
||||
use colored::*;
|
||||
#[cfg(feature = "history")]
|
||||
use directories::ProjectDirs;
|
||||
use failure::{err_msg, Fail};
|
||||
#[cfg(feature = "clipboard-crate")]
|
||||
use failure::{Compat, Error};
|
||||
|
@ -40,6 +35,7 @@ use ffsend_api::{
|
|||
reqwest,
|
||||
url::Url,
|
||||
};
|
||||
use fs2::available_space;
|
||||
use rand::distributions::Alphanumeric;
|
||||
use rand::{thread_rng, Rng};
|
||||
use regex::Regex;
|
||||
|
@ -295,14 +291,14 @@ pub fn highlight_info(msg: &str) -> ColoredString {
|
|||
}
|
||||
|
||||
/// Open the given URL in the users default browser.
|
||||
/// The browsers exit statis is returned.
|
||||
pub fn open_url(url: impl Borrow<Url>) -> Result<ExitStatus, IoError> {
|
||||
/// The browsers exit status is returned.
|
||||
pub fn open_url(url: impl Borrow<Url>) -> Result<(), IoError> {
|
||||
open_path(url.borrow().as_str())
|
||||
}
|
||||
|
||||
/// Open the given path or URL using the program configured on the system.
|
||||
/// The program exit statis is returned.
|
||||
pub fn open_path(path: &str) -> Result<ExitStatus, IoError> {
|
||||
/// The program exit status is returned.
|
||||
pub fn open_path(path: &str) -> Result<(), IoError> {
|
||||
open::that(path)
|
||||
}
|
||||
|
||||
|
@ -322,7 +318,7 @@ pub fn set_clipboard(content: String) -> Result<(), ClipboardError> {
|
|||
/// native clipboard interface only has a lifetime of the application. This means that the
|
||||
/// clipboard is instantly cleared as soon as this application quits, which is always immediately.
|
||||
/// This limitation is due to security reasons as defined by X11. The alternative binaries we set
|
||||
/// the clipboard with spawn a daemon in the background to keep the clipboad alive until it's
|
||||
/// the clipboard with spawn a daemon in the background to keep the clipboard alive until it's
|
||||
/// flushed.
|
||||
#[cfg(feature = "clipboard")]
|
||||
#[derive(Clone, Eq, PartialEq)]
|
||||
|
@ -495,7 +491,7 @@ pub enum ClipboardError {
|
|||
#[fail(display = "failed to access clipboard using {}", _0)]
|
||||
BinaryIo(&'static str, #[cause] IoError),
|
||||
|
||||
/// `xclip` or `xsel` unexpectetly exited with a non-successful status code.
|
||||
/// `xclip` or `xsel` unexpectedly exited with a non-successful status code.
|
||||
#[cfg(feature = "clipboard-bin")]
|
||||
#[fail(
|
||||
display = "failed to use clipboard, {} exited with status code {}",
|
||||
|
@ -504,8 +500,8 @@ pub enum ClipboardError {
|
|||
BinaryStatus(&'static str, i32),
|
||||
}
|
||||
|
||||
/// Check for an emtpy password in the given `password`.
|
||||
/// If the password is emtpy the program will quit with an error unless
|
||||
/// Check for an empty password in the given `password`.
|
||||
/// If the password is empty the program will quit with an error unless
|
||||
/// forced.
|
||||
// TODO: move this to a better module
|
||||
pub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {
|
||||
|
@ -523,7 +519,7 @@ pub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {
|
|||
|
||||
/// Prompt the user to enter a password.
|
||||
///
|
||||
/// If `empty` is `false`, emtpy passwords aren't allowed unless forced.
|
||||
/// If `empty` is `false`, empty passwords aren't allowed unless forced.
|
||||
pub fn prompt_password(main_matcher: &MainMatcher, optional: bool) -> Option<String> {
|
||||
// Quit with an error if we may not interact
|
||||
if !optional && main_matcher.no_interact() {
|
||||
|
@ -553,7 +549,7 @@ pub fn prompt_password(main_matcher: &MainMatcher, optional: bool) -> Option<Str
|
|||
}
|
||||
}
|
||||
|
||||
// On input error, propegate the error or don't use a password if optional
|
||||
// On input error, propagate the error or don't use a password if optional
|
||||
Err(err) => {
|
||||
if !optional {
|
||||
quit_error(
|
||||
|
@ -596,7 +592,7 @@ pub fn ensure_password(
|
|||
return false;
|
||||
}
|
||||
|
||||
// Check whehter we allow interaction
|
||||
// Check whether we allow interaction
|
||||
let interact = !main_matcher.no_interact();
|
||||
|
||||
loop {
|
||||
|
@ -765,7 +761,7 @@ pub fn ensure_owner_token(
|
|||
main_matcher: &MainMatcher,
|
||||
optional: bool,
|
||||
) -> bool {
|
||||
// Check whehter we allow interaction
|
||||
// Check whether we allow interaction
|
||||
let interact = !main_matcher.no_interact();
|
||||
|
||||
// Notify that an owner token is required
|
||||
|
@ -988,7 +984,7 @@ pub fn ensure_enough_space<P: AsRef<Path>>(path: P, size: u64) {
|
|||
}
|
||||
};
|
||||
|
||||
// Return if enough disk space is avaiable
|
||||
// Return if enough disk space is available
|
||||
if space >= size {
|
||||
return;
|
||||
}
|
||||
|
@ -1132,7 +1128,31 @@ impl From<ResponseError> for FollowError {
|
|||
pub fn rand_alphanum_string(len: usize) -> String {
|
||||
let mut rng = thread_rng();
|
||||
iter::repeat(())
|
||||
.map(|()| rng.sample(Alphanumeric))
|
||||
.map(|()| rng.sample(Alphanumeric) as char)
|
||||
.take(len)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Read file from stdin.
|
||||
pub fn stdin_read_file(prompt: bool) -> Result<Vec<u8>, StdinErr> {
|
||||
if prompt {
|
||||
#[cfg(not(windows))]
|
||||
eprintln!("Enter input. Use [CTRL+D] to stop:");
|
||||
#[cfg(windows)]
|
||||
eprintln!("Enter input. Use [CTRL+Z] to stop:");
|
||||
}
|
||||
|
||||
let mut data = vec![];
|
||||
io::stdin()
|
||||
.lock()
|
||||
.read_to_end(&mut data)
|
||||
.map_err(StdinErr::Stdin)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
/// URL following error.
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum StdinErr {
|
||||
#[fail(display = "failed to read from stdin")]
|
||||
Stdin(#[cause] io::Error),
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue