mirror of
https://github.com/timvisee/ffsend.git
synced 2025-10-03 09:39:15 +02:00
Compare commits
83 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b6d7c6983a | ||
![]() |
88bffdb79e | ||
![]() |
f5b606fca0 | ||
![]() |
60b3df030e | ||
![]() |
0b32f4f71b | ||
![]() |
754735d2db | ||
![]() |
92ed3eca9d | ||
![]() |
a7143bb1ee | ||
![]() |
0e7884d13a | ||
![]() |
c87845770d | ||
![]() |
2c9d60d5c1 | ||
![]() |
27439fb72f | ||
![]() |
07f3ff8777 | ||
![]() |
1da996783f | ||
![]() |
238f1f54d7 | ||
![]() |
5df8463b74 | ||
![]() |
8d8ad7fdb3 | ||
![]() |
f06b639542 | ||
![]() |
5fd2eac6eb | ||
![]() |
e0821c751d | ||
![]() |
3c1c2dc28c | ||
![]() |
6fdc6ad85c | ||
![]() |
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 |
33 changed files with 1276 additions and 1077 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -2,3 +2,4 @@
|
||||||
target/
|
target/
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
.idea/
|
.idea/
|
||||||
|
snapcraft.login
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
# - export a build artifact from the new job
|
# - export a build artifact from the new job
|
||||||
# - manually upload artifact to GitHub in the 'github-release' job
|
# - manually upload artifact to GitHub in the 'github-release' job
|
||||||
|
|
||||||
image: "rust:slim"
|
image: "rust:slim-bookworm"
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- check
|
- check
|
||||||
|
@ -64,10 +64,10 @@ check-nightly:
|
||||||
<<: *check-base
|
<<: *check-base
|
||||||
variables:
|
variables:
|
||||||
RUST_VERSION: nightly
|
RUST_VERSION: nightly
|
||||||
check-old:
|
check-msrv:
|
||||||
<<: *check-base
|
<<: *check-base
|
||||||
variables:
|
variables:
|
||||||
RUST_VERSION: "1.43.0"
|
RUST_VERSION: "1.63.0"
|
||||||
|
|
||||||
# Build using Rust stable
|
# Build using Rust stable
|
||||||
build-x86_64-linux-gnu:
|
build-x86_64-linux-gnu:
|
||||||
|
@ -95,17 +95,17 @@ build-x86_64-linux-musl:
|
||||||
|
|
||||||
# Build OpenSSL statically
|
# Build OpenSSL statically
|
||||||
- apt-get install -y build-essential wget musl-tools
|
- 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
|
- wget https://github.com/openssl/openssl/releases/download/openssl-3.0.15/openssl-3.0.15.tar.gz
|
||||||
- tar xzvf openssl-1.0.2o.tar.gz
|
- tar xzvf openssl-3.0.15.tar.gz
|
||||||
- cd openssl-1.0.2o
|
- cd openssl-3.0.15
|
||||||
- ./config -fPIC --openssldir=/usr/local/ssl --prefix=/usr/local
|
- ./config no-async -fPIC --openssldir=/usr/local/ssl --prefix=/usr/local
|
||||||
- make
|
- make
|
||||||
- make install
|
- make install
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|
||||||
# Statically build ffsend
|
# Statically build ffsend
|
||||||
- export OPENSSL_STATIC=1
|
- export OPENSSL_STATIC=1
|
||||||
- export OPENSSL_LIB_DIR=/usr/local/lib
|
- export OPENSSL_LIB_DIR=/usr/local/lib64
|
||||||
- export OPENSSL_INCLUDE_DIR=/usr/local/include
|
- export OPENSSL_INCLUDE_DIR=/usr/local/include
|
||||||
- cargo build --target=$RUST_TARGET --release --verbose
|
- cargo build --target=$RUST_TARGET --release --verbose
|
||||||
|
|
||||||
|
@ -187,8 +187,7 @@ release-snap:
|
||||||
|
|
||||||
# Publish snap package
|
# Publish snap package
|
||||||
- echo "Publishing snap package..."
|
- echo "Publishing snap package..."
|
||||||
- echo "$SNAPCRAFT_LOGIN" | base64 -d > snapcraft.login
|
- snapcraft whoami
|
||||||
- snapcraft login --with snapcraft.login
|
|
||||||
- snapcraft push --release=stable ffsend_*_amd64.snap
|
- snapcraft push --release=stable ffsend_*_amd64.snap
|
||||||
artifacts:
|
artifacts:
|
||||||
name: ffsend-snap-x86_64
|
name: ffsend-snap-x86_64
|
||||||
|
@ -256,7 +255,7 @@ release-docker:
|
||||||
|
|
||||||
# AUR packages release
|
# AUR packages release
|
||||||
package-aur:
|
package-aur:
|
||||||
image: archlinux/base
|
image: archlinux
|
||||||
stage: package
|
stage: package
|
||||||
needs:
|
needs:
|
||||||
- release-github
|
- release-github
|
||||||
|
@ -301,7 +300,7 @@ package-aur:
|
||||||
- sed "s/^pkgver=.*\$/pkgver=$VERSION/" -i ffsend/PKGBUILD
|
- sed "s/^pkgver=.*\$/pkgver=$VERSION/" -i ffsend/PKGBUILD
|
||||||
- sed "s/^pkgver=.*\$/pkgver=$VERSION/" -i ffsend-bin/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/^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::\).*\"/\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.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
|
- sed "s/\(\"ffsend-v\$pkgver.zsh::\).*\"/\1$(echo $URL_ZSH_COMPLETION | sed 's/\//\\\//g')\"/" -i ffsend-bin/PKGBUILD
|
||||||
|
|
|
@ -115,7 +115,7 @@ members of the project's leadership.
|
||||||
|
|
||||||
### Attribution
|
### Attribution
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][coc-homepage], version 1.4,
|
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
|
## License
|
||||||
This project is released under the GNU GPL-3.0 license.
|
This project is released under the GNU GPL-3.0 license.
|
||||||
|
@ -128,5 +128,5 @@ Check out the [LICENSE](LICENSE) file for more information.
|
||||||
[github]: https://github.com/timvisee/ffsend
|
[github]: https://github.com/timvisee/ffsend
|
||||||
[github-issues]: https://github.com/timvisee/ffsend/issues
|
[github-issues]: https://github.com/timvisee/ffsend/issues
|
||||||
[github-pr]: https://github.com/timvisee/ffsend/pulls
|
[github-pr]: https://github.com/timvisee/ffsend/pulls
|
||||||
[coc-homepage]: http://contributor-covenant.org
|
[coc-homepage]: https://contributor-covenant.org
|
||||||
[coc-version]: http://contributor-covenant.org/version/1/4/
|
[coc-version]: https://contributor-covenant.org/version/1/4/
|
||||||
|
|
1804
Cargo.lock
generated
1804
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
35
Cargo.toml
35
Cargo.toml
|
@ -1,6 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ffsend"
|
name = "ffsend"
|
||||||
version = "0.2.69"
|
version = "0.2.77"
|
||||||
|
rust-version = "1.63.0"
|
||||||
authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
|
authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -8,7 +9,7 @@ homepage = "https://timvisee.com/projects/ffsend"
|
||||||
repository = "https://gitlab.com/timvisee/ffsend"
|
repository = "https://gitlab.com/timvisee/ffsend"
|
||||||
description = """\
|
description = """\
|
||||||
Easily and securely share files from the command line.\n\
|
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"]
|
keywords = ["send", "firefox", "cli"]
|
||||||
categories = [
|
categories = [
|
||||||
|
@ -49,24 +50,12 @@ license-file = ["LICENSE", "3"]
|
||||||
depends = "$auto, libssl1.1, ca-certificates, xclip"
|
depends = "$auto, libssl1.1, ca-certificates, xclip"
|
||||||
maintainer-scripts = "pkg/deb"
|
maintainer-scripts = "pkg/deb"
|
||||||
|
|
||||||
[badges]
|
|
||||||
gitlab = { repository = "timvisee/ffsend", branch = "master" }
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "ffsend"
|
name = "ffsend"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
default = ["archive", "clipboard", "crypto-ring", "history", "infer-command", "qrcode", "send3", "urlshorten"]
|
||||||
"archive",
|
|
||||||
"clipboard",
|
|
||||||
"crypto-ring",
|
|
||||||
"history",
|
|
||||||
"infer-command",
|
|
||||||
"qrcode",
|
|
||||||
"send3",
|
|
||||||
"urlshorten",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Compile with file archiving support
|
# Compile with file archiving support
|
||||||
archive = ["tar"]
|
archive = ["tar"]
|
||||||
|
@ -77,10 +66,10 @@ clipboard = ["clip", "which"]
|
||||||
# Compile with file history support
|
# Compile with file history support
|
||||||
history = []
|
history = []
|
||||||
|
|
||||||
# Support for Firefox Send v2
|
# Support for Send v2
|
||||||
send2 = ["ffsend-api/send2"]
|
send2 = ["ffsend-api/send2"]
|
||||||
|
|
||||||
# Support for Firefox Send v3
|
# Support for Send v3
|
||||||
send3 = ["ffsend-api/send3"]
|
send3 = ["ffsend-api/send3"]
|
||||||
|
|
||||||
# Use OpenSSL as cryptography backend
|
# Use OpenSSL as cryptography backend
|
||||||
|
@ -113,19 +102,19 @@ chrono = "0.4"
|
||||||
clap = "2.33"
|
clap = "2.33"
|
||||||
colored = "2.0"
|
colored = "2.0"
|
||||||
derive_builder = "0.10"
|
derive_builder = "0.10"
|
||||||
directories = "3.0"
|
directories = "4.0"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
ffsend-api = { version = "0.7.2", default-features = false }
|
ffsend-api = { version = "0.7.3", default-features = false }
|
||||||
fs2 = "0.4"
|
fs2 = "0.4"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
open = "1"
|
open = "2"
|
||||||
openssl-probe = "0.1"
|
openssl-probe = "0.1"
|
||||||
pathdiff = "0.2"
|
pathdiff = "0.2"
|
||||||
pbr = "1"
|
pbr = "1"
|
||||||
prettytable-rs = "0.8"
|
prettytable-rs = { version = "0.10.0", default-features = false }
|
||||||
qr2term = { version = "0.2", optional = true }
|
qr2term = { version = "0.2", optional = true }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
regex = "1.3"
|
regex = "1.5"
|
||||||
rpassword = "5"
|
rpassword = "5"
|
||||||
serde = "1"
|
serde = "1"
|
||||||
serde_derive = "1"
|
serde_derive = "1"
|
||||||
|
@ -133,7 +122,7 @@ tar = { version = "0.4", optional = true }
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
toml = "0.5"
|
toml = "0.5"
|
||||||
urlshortener = { version = "3", optional = true }
|
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]
|
[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 }
|
which = { version = "4.0", optional = true }
|
||||||
|
|
55
LICENSE
55
LICENSE
|
@ -1,7 +1,7 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
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
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
@ -619,3 +619,56 @@ Program, unless a warranty or assumption of liability accompanies a
|
||||||
copy of the Program in return for a fee.
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
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 <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
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
|
||||||
|
<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
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|
76
README.md
76
README.md
|
@ -8,14 +8,14 @@
|
||||||
[gitlab-ci-link]: https://gitlab.com/timvisee/ffsend/pipelines
|
[gitlab-ci-link]: https://gitlab.com/timvisee/ffsend/pipelines
|
||||||
[gitlab-ci-master-badge]: https://gitlab.com/timvisee/ffsend/badges/master/pipeline.svg
|
[gitlab-ci-master-badge]: https://gitlab.com/timvisee/ffsend/badges/master/pipeline.svg
|
||||||
|
|
||||||
*Notice: the default Send host is provided by [@timvisee][timvisee],
|
*Notice: the default Send host is provided by [@timvisee][timvisee]
|
||||||
[info](https://gitlab.com/timvisee/ffsend/-/issues/101).
|
([info](https://gitlab.com/timvisee/ffsend/-/issues/111)).
|
||||||
Please consider to [donate] and help keep it running.*
|
Please consider to [donate] and help keep it running.*
|
||||||
|
|
||||||
# ffsend
|
# ffsend
|
||||||
|
|
||||||
> Easily and securely share files from the command line.
|
> 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
|
Easily and securely share files and directories from the command line through a
|
||||||
safe, private and encrypted link using a single simple command.
|
safe, private and encrypted link using a single simple command.
|
||||||
|
@ -36,7 +36,7 @@ Find out more about security [here](#security).
|
||||||
- [Features](#features)
|
- [Features](#features)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Requirements](#requirements)
|
- [Requirements](#requirements)
|
||||||
- [Install](#install) ([Linux](#linux-all-distributions), [macOS](#macos), [Windows](#windows), [FreeBSD](#freebsd), [Android](#android), [_Other OS/arch_](#other-os-or-architecture))
|
- [Install](#install) ([Linux](#linux-all-distributions), [macOS](#macos), [Windows](#windows), [FreeBSD](#freebsd), [Android](#android), [_Other OS/architecture_](#other-os-or-architecture))
|
||||||
- [Build](#build)
|
- [Build](#build)
|
||||||
- [Configuration and environment](#configuration-and-environment)
|
- [Configuration and environment](#configuration-and-environment)
|
||||||
- [Security](#security)
|
- [Security](#security)
|
||||||
|
@ -45,9 +45,9 @@ Find out more about security [here](#security).
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
The public [Send][send] service that is used as default host is provided by
|
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
|
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_
|
_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
|
- Additional password protection, generation and configurable download limits
|
||||||
- File and directory archiving and extraction
|
- File and directory archiving and extraction
|
||||||
- Built-in share URL shortener and QR code generator
|
- 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
|
- History tracking your files for easy management
|
||||||
- Ability to use your own Send hosts
|
- Ability to use your own Send hosts
|
||||||
- Inspect or delete shared files
|
- Inspect or delete shared files
|
||||||
|
@ -74,7 +74,7 @@ Easily upload and download:
|
||||||
```bash
|
```bash
|
||||||
# Simple upload
|
# Simple upload
|
||||||
$ ffsend upload my-file.txt
|
$ ffsend upload my-file.txt
|
||||||
https://send.firefox.com/#sample-share-url
|
https://send.vis.ee/#sample-share-url
|
||||||
|
|
||||||
# Advanced upload
|
# Advanced upload
|
||||||
# - Specify a download limit of 1
|
# - Specify a download limit of 1
|
||||||
|
@ -85,25 +85,25 @@ https://send.firefox.com/#sample-share-url
|
||||||
# - Open the shareable link in your browser
|
# - Open the shareable link in your browser
|
||||||
$ ffsend upload --downloads 1 --expiry-time 5m --password --archive --copy --open my-file.txt
|
$ ffsend upload --downloads 1 --expiry-time 5m --password --archive --copy --open my-file.txt
|
||||||
Password: ******
|
Password: ******
|
||||||
https://send.firefox.com/#sample-share-url
|
https://send.vis.ee/#sample-share-url
|
||||||
|
|
||||||
# Upload to your own host
|
# Upload to your own host
|
||||||
$ ffsend u -h https://example.com/ my-file.txt
|
$ ffsend u -h https://example.com/ my-file.txt
|
||||||
https://example.com/#sample-share-url
|
https://example.com/#sample-share-url
|
||||||
|
|
||||||
# Simple download
|
# Simple download
|
||||||
$ ffsend download https://send.firefox.com/#sample-share-url
|
$ ffsend download https://send.vis.ee/#sample-share-url
|
||||||
```
|
```
|
||||||
|
|
||||||
Inspect remote files:
|
Inspect remote files:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Check if a file exists
|
# 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
|
Exists: yes
|
||||||
|
|
||||||
# Fetch remote file info
|
# Fetch remote file info
|
||||||
$ ffsend info https://send.firefox.com/#sample-share-url
|
$ ffsend info https://send.vis.ee/#sample-share-url
|
||||||
ID: b087066715
|
ID: b087066715
|
||||||
Name: my-file.txt
|
Name: my-file.txt
|
||||||
Size: 12 KiB
|
Size: 12 KiB
|
||||||
|
@ -118,16 +118,16 @@ Other commands include:
|
||||||
# View your file history
|
# View your file history
|
||||||
$ ffsend history
|
$ ffsend history
|
||||||
# LINK EXPIRE
|
# LINK EXPIRE
|
||||||
1 https://send.firefox.com/#sample-share-url 23h57m
|
1 https://send.vis.ee/#sample-share-url 23h57m
|
||||||
2 https://send.firefox.com/#other-sample-url 17h38m
|
2 https://send.vis.ee/#other-sample-url 17h38m
|
||||||
3 https://example.com/#sample-share-url 37m30s
|
3 https://example.com/#sample-share-url 37m30s
|
||||||
|
|
||||||
# Change the password after uploading
|
# Change the password after uploading
|
||||||
$ ffsend password https://send.firefox.com/#sample-share-url
|
$ ffsend password https://send.vis.ee/#sample-share-url
|
||||||
Password: ******
|
Password: ******
|
||||||
|
|
||||||
# Delete a file
|
# 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
|
Use the `--help` flag, `help` subcommand, or see the [help](#help) section for
|
||||||
|
@ -188,6 +188,7 @@ _Note: due to how `snap` is configured by default, you won't be able to use the
|
||||||
package from some contexts such as through SSH without manual modifications. If
|
package from some contexts such as through SSH without manual modifications. If
|
||||||
you're experiencing problems, please refer to a different installation method
|
you're experiencing problems, please refer to a different installation method
|
||||||
such as the [prebuilt binaries](#linux-prebuilt-binaries), or open an issue._
|
such as the [prebuilt binaries](#linux-prebuilt-binaries), or open an issue._
|
||||||
|
_Note: if you want to read/write to a flash drive run `snap connect ffsend:removable-media`
|
||||||
|
|
||||||
[» `ffsend`][snapcraft-ffsend]
|
[» `ffsend`][snapcraft-ffsend]
|
||||||
|
|
||||||
|
@ -275,7 +276,7 @@ ffsend --help
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
Using the [`homebrew` package](#macos-homebrew-package) is recommended.
|
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).
|
[prebuilt binaries](#macos-prebuilt-binaries).
|
||||||
|
|
||||||
#### macOS: homebrew package
|
#### macOS: homebrew package
|
||||||
|
@ -286,6 +287,17 @@ brew install ffsend
|
||||||
ffsend --help
|
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
|
#### macOS: Nix package
|
||||||
_Note: The Nix package is currently not automatically updated, and might be
|
_Note: The Nix package is currently not automatically updated, and might be
|
||||||
slightly outdated._
|
slightly outdated._
|
||||||
|
@ -351,7 +363,7 @@ You can use `ffsend` from the command line in the same directory:
|
||||||
.\ffsend.exe --help
|
.\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`:
|
your systems `PATH`. The easiest solution is to move it into `System32`:
|
||||||
```cmd
|
```cmd
|
||||||
move .\ffsend.exe C:\Windows\System32\ffsend.exe
|
move .\ffsend.exe C:\Windows\System32\ffsend.exe
|
||||||
|
@ -407,7 +419,7 @@ docker run --rm -it -v $(pwd):/data timvisee/ffsend
|
||||||
docker run --rm -it -v $(pwd):/data timvisee/ffsend upload my-file.txt
|
docker run --rm -it -v $(pwd):/data timvisee/ffsend upload my-file.txt
|
||||||
|
|
||||||
# Download from specified link
|
# 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
|
# Show help
|
||||||
docker run --rm -it -v $(pwd):/data timvisee/ffsend help
|
docker run --rm -it -v $(pwd):/data timvisee/ffsend help
|
||||||
|
@ -417,7 +429,7 @@ docker pull timvisee/ffsend
|
||||||
```
|
```
|
||||||
|
|
||||||
On Linux or macOS you might define a alias in your shell configuration, to make
|
On Linux or macOS you might define a alias in your shell configuration, to make
|
||||||
it invokable as `ffsend`:
|
it invocable as `ffsend`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
alias ffsend='docker run --rm -it -v "$(pwd):/data" timvisee/ffsend'
|
alias ffsend='docker run --rm -it -v "$(pwd):/data" timvisee/ffsend'
|
||||||
|
@ -433,7 +445,7 @@ before proceeding:
|
||||||
### Build requirements
|
### Build requirements
|
||||||
- Runtime [requirements](#requirements)
|
- Runtime [requirements](#requirements)
|
||||||
- [`git`][git]
|
- [`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:
|
- [OpenSSL][openssl] or [LibreSSL][libressl] libraries/headers:
|
||||||
- Linux:
|
- Linux:
|
||||||
- Ubuntu, Debian and derivatives: `apt install build-essential cmake pkg-config libssl-dev`
|
- Ubuntu, Debian and derivatives: `apt install build-essential cmake pkg-config libssl-dev`
|
||||||
|
@ -501,8 +513,8 @@ The following features are available, some of which are enabled by default:
|
||||||
|
|
||||||
| Feature | Enabled | Description |
|
| Feature | Enabled | Description |
|
||||||
| :-------------: | :-----: | :--------------------------------------------------------- |
|
| :-------------: | :-----: | :--------------------------------------------------------- |
|
||||||
| `send2` | Default | Support for Firefox Send v2 servers |
|
| `send2` | Default | Support for Send v2 servers |
|
||||||
| `send3` | Default | Support for Firefox Send v3 servers |
|
| `send3` | Default | Support for Send v3 servers |
|
||||||
| `crypto-ring` | Default | Use ring as cryptography backend |
|
| `crypto-ring` | Default | Use ring as cryptography backend |
|
||||||
| `crypto-openssl`| | Use OpenSSL as cryptography backend |
|
| `crypto-openssl`| | Use OpenSSL as cryptography backend |
|
||||||
| `clipboard` | Default | Support for copying links to the clipboard |
|
| `clipboard` | Default | Support for copying links to the clipboard |
|
||||||
|
@ -546,6 +558,7 @@ to command line arguments:
|
||||||
| `FFSEND_TIMEOUT` | `--timeout <SECONDS>` | Request timeout (0 to disable) |
|
| `FFSEND_TIMEOUT` | `--timeout <SECONDS>` | Request timeout (0 to disable) |
|
||||||
| `FFSEND_TRANSFER_TIMEOUT` | `--transfer-timeout <SECONDS>` | Transfer 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_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_API` | `--api <VERSION>` | Server API version, `-` to lookup |
|
||||||
| `FFSEND_BASIC_AUTH` | `--basic-auth <USER:PASSWORD>` | Basic HTTP authentication credentials to use. |
|
| `FFSEND_BASIC_AUTH` | `--basic-auth <USER:PASSWORD>` | Basic HTTP authentication credentials to use. |
|
||||||
|
|
||||||
|
@ -583,7 +596,7 @@ having `ffput` and `ffget` just for to upload and download using `ffsend`.
|
||||||
This allows simple and direct commands like:
|
This allows simple and direct commands like:
|
||||||
```bash
|
```bash
|
||||||
ffput my-file.txt
|
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:
|
This works for a predefined list of binary names:
|
||||||
|
@ -732,10 +745,10 @@ documentation [here][send-encryption].
|
||||||
```
|
```
|
||||||
$ ffsend help
|
$ ffsend help
|
||||||
|
|
||||||
ffsend 0.2.69
|
ffsend 0.2.72
|
||||||
Tim Visee <3a4fb3964f@sinenomine.email>
|
Tim Visee <3a4fb3964f@sinenomine.email>
|
||||||
Easily and securely share files from the command line.
|
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.
|
The default public Send host is provided by Tim Visee, @timvisee.
|
||||||
Please consider to donate and help keep it running: https://vis.ee/donate
|
Please consider to donate and help keep it running: https://vis.ee/donate
|
||||||
|
@ -774,12 +787,12 @@ SUBCOMMANDS:
|
||||||
password Change the password of a shared file [aliases: pass, p]
|
password Change the password of a shared file [aliases: pass, p]
|
||||||
version Determine the Send server version [aliases: v]
|
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
|
## Special thanks
|
||||||
- to all `ffsend` source/package contributors
|
- 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
|
- to everyone involved with [asciinema][asciinema] and [svg-term][svg-term] for
|
||||||
providing tools to make great visual demos
|
providing tools to make great visual demos
|
||||||
- to everyone involved in all crate dependencies used
|
- to everyone involved in all crate dependencies used
|
||||||
|
@ -799,8 +812,10 @@ Check out the [LICENSE](LICENSE) file for more information.
|
||||||
[termux]: https://termux.com/
|
[termux]: https://termux.com/
|
||||||
[rust]: https://rust-lang.org/
|
[rust]: https://rust-lang.org/
|
||||||
[rustup]: https://rustup.rs/
|
[rustup]: https://rustup.rs/
|
||||||
[send]: https://send.firefox.com/
|
[send]: https://github.com/timvisee/send
|
||||||
[send-encryption]: https://github.com/mozilla/send/blob/master/docs/encryption.md
|
[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/
|
[asciinema]: https://asciinema.org/
|
||||||
[svg-term]: https://github.com/marionebl/svg-term-cli
|
[svg-term]: https://github.com/marionebl/svg-term-cli
|
||||||
[github-releases]: https://github.com/timvisee/ffsend/releases
|
[github-releases]: https://github.com/timvisee/ffsend/releases
|
||||||
|
@ -817,6 +832,5 @@ Check out the [LICENSE](LICENSE) file for more information.
|
||||||
[docker-hub-ffsend]: https://hub.docker.com/r/timvisee/ffsend
|
[docker-hub-ffsend]: https://hub.docker.com/r/timvisee/ffsend
|
||||||
[scoop-install]: https://scoop.sh/#installs-in-seconds
|
[scoop-install]: https://scoop.sh/#installs-in-seconds
|
||||||
[freshports-ffsend]: https://www.freshports.org/www/ffsend
|
[freshports-ffsend]: https://www.freshports.org/www/ffsend
|
||||||
[issue116]: https://github.com/timvisee/ffsend/issues/116
|
|
||||||
[timvisee]: https://timvisee.com/
|
[timvisee]: https://timvisee.com/
|
||||||
[donate]: https://timvisee.com/donate
|
[donate]: https://timvisee.com/donate
|
||||||
|
|
|
@ -4,5 +4,5 @@
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "Generating all completions using cargo debug binary..."
|
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."
|
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
|
pkgname=ffsend
|
||||||
pkgver=0.2.62
|
pkgver=0.2.62
|
||||||
pkgrel=0
|
pkgrel=0
|
||||||
pkgdesc=" A fully featured Firefox Send client"
|
pkgdesc=" A fully featured Send client"
|
||||||
url="https://gitlab.com/timvisee/ffsend"
|
url="https://gitlab.com/timvisee/ffsend"
|
||||||
arch="x86_64 x86 armhf armv7 aarch64 ppc64le" # limited by cargo
|
arch="x86_64 x86 armhf armv7 aarch64 ppc64le" # limited by cargo
|
||||||
license="GPL-3.0-only"
|
license="GPL-3.0-only"
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
pkgname=ffsend-bin
|
pkgname=ffsend-bin
|
||||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||||
pkgrel=1
|
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"
|
url="https://gitlab.com/timvisee/ffsend"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
source=("ffsend-v$pkgver::https://github.com/timvisee/ffsend/releases/download/v$pkgver/ffsend-v$pkgver-linux-x64-static"
|
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() {
|
package() {
|
||||||
cd "$srcdir"
|
cd "$srcdir"
|
||||||
|
|
||||||
# Install Binary
|
|
||||||
install -Dm755 "ffsend-v$pkgver" "$pkgdir/usr/bin/ffsend"
|
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.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.zsh" "$pkgdir/usr/share/zsh/site-functions/_ffsend"
|
||||||
install -Dm644 "ffsend-v$pkgver.fish" "$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish"
|
install -Dm644 "ffsend-v$pkgver.fish" "$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish"
|
||||||
|
|
|
@ -7,31 +7,45 @@
|
||||||
pkgname=ffsend-git
|
pkgname=ffsend-git
|
||||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||||
pkgrel=1
|
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"
|
url="https://gitlab.com/timvisee/ffsend"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
source=("ffsend::git+$url.git")
|
source=("git+${url}")
|
||||||
sha256sums=('SKIP')
|
sha256sums=('SKIP')
|
||||||
arch=('x86_64' 'i686')
|
arch=('x86_64' 'i686')
|
||||||
provides=('ffsend')
|
provides=('ffsend')
|
||||||
conflicts=('ffsend')
|
conflicts=('ffsend')
|
||||||
depends=('ca-certificates')
|
depends=('ca-certificates')
|
||||||
makedepends=('openssl>=1.0' 'rust>=1.39' 'cargo' 'cmake')
|
makedepends=('cargo' 'cmake' 'openssl>=1.0')
|
||||||
optdepends=('xclip: clipboard support'
|
optdepends=('xclip: clipboard support')
|
||||||
'bash-completion: support auto completion for bash')
|
|
||||||
|
prepare() {
|
||||||
|
cd "${pkgname%-git}"
|
||||||
|
|
||||||
|
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd ffsend
|
cd "${pkgname%-git}"
|
||||||
env CARGO_INCREMENTAL=0 cargo build --release
|
|
||||||
|
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() {
|
package() {
|
||||||
cd "$srcdir/ffsend"
|
cd "${pkgname%-git}"
|
||||||
|
|
||||||
# Install Binary
|
install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/ffsend"
|
||||||
install -Dm755 "./target/release/ffsend" "$pkgdir/usr/bin/ffsend"
|
|
||||||
|
|
||||||
# Install shell completions and LICENSE file
|
# Shell completions and LICENSE file
|
||||||
install -Dm644 "contrib/completions/ffsend.bash" \
|
install -Dm644 "contrib/completions/ffsend.bash" \
|
||||||
"$pkgdir/etc/bash_completion.d/ffsend"
|
"$pkgdir/etc/bash_completion.d/ffsend"
|
||||||
install -Dm644 "contrib/completions/_ffsend" \
|
install -Dm644 "contrib/completions/_ffsend" \
|
||||||
|
|
|
@ -7,30 +7,43 @@
|
||||||
pkgname=ffsend
|
pkgname=ffsend
|
||||||
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
pkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml
|
||||||
pkgrel=1
|
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"
|
url="https://gitlab.com/timvisee/ffsend"
|
||||||
license=('GPL3')
|
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
|
sha256sums=('SKIP') # automatically set in CI, see: /.gitlab-ci.yml
|
||||||
arch=('x86_64' 'i686')
|
arch=('x86_64' 'i686')
|
||||||
provides=('ffsend')
|
|
||||||
depends=('ca-certificates')
|
depends=('ca-certificates')
|
||||||
makedepends=('openssl>=1.0' 'rust>=1.39' 'cargo' 'cmake')
|
makedepends=('cargo' 'cmake' 'openssl>=1.0')
|
||||||
optdepends=('xclip: clipboard support'
|
optdepends=('xclip: clipboard support')
|
||||||
'bash-completion: support auto completion for bash')
|
|
||||||
|
prepare() {
|
||||||
|
cd "$pkgname-v$pkgver"
|
||||||
|
|
||||||
|
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
cd "ffsend-v$pkgver"
|
cd "$pkgname-v$pkgver"
|
||||||
env CARGO_INCREMENTAL=0 cargo build --release
|
|
||||||
|
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() {
|
package() {
|
||||||
cd "$srcdir/ffsend-v$pkgver"
|
cd "$pkgname-v$pkgver"
|
||||||
|
|
||||||
# Install Binary
|
install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
|
||||||
install -Dm755 "./target/release/ffsend" "$pkgdir/usr/bin/ffsend"
|
|
||||||
|
|
||||||
# Install shell completions and LICENSE file
|
# Shell completions and LICENSE file
|
||||||
install -Dm644 "contrib/completions/ffsend.bash" \
|
install -Dm644 "contrib/completions/ffsend.bash" \
|
||||||
"$pkgdir/etc/bash_completion.d/ffsend"
|
"$pkgdir/etc/bash_completion.d/ffsend"
|
||||||
install -Dm644 "contrib/completions/_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>
|
<docsUrl>https://github.com/timvisee/ffsend</docsUrl>
|
||||||
<bugTrackerUrl>https://gitlab.com/timvisee/ffsend/issues</bugTrackerUrl>
|
<bugTrackerUrl>https://gitlab.com/timvisee/ffsend/issues</bugTrackerUrl>
|
||||||
<tags>ffsend firefox-send cli file-sharing file-upload encryption rust</tags>
|
<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>
|
<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 Firefox Send client.</description>
|
<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 -->
|
<!-- 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
|
fi
|
||||||
|
|
||||||
# Ensure the debian architecture is set
|
# 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"
|
echo "Error: debian architecture not configured in \$DEB_ARCH"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Define some useful variables
|
# Define some useful variables
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||||
VERSION=${TRAVIS_TAG:1}
|
VERSION=${TRAVIS_TAG:1}
|
||||||
|
|
||||||
# Ensure the binary file exists
|
# Ensure the binary file exists
|
||||||
|
@ -25,23 +25,23 @@ if [[ ! -f "$DIR/../ffsend" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create an application directory, copy the binary into it
|
# Create an application directory, copy the binary into it
|
||||||
mkdir -p $DIR/ffsend-$VERSION
|
mkdir -p "$DIR/ffsend-$VERSION"
|
||||||
cp $DIR/../ffsend $DIR/ffsend-$VERSION/ffsend
|
cp -- "$DIR/../ffsend" "$DIR/ffsend-$VERSION/ffsend"
|
||||||
|
|
||||||
# Create an application tarbal
|
# Create an application tarball
|
||||||
cd $DIR/..
|
cd -- "$DIR/.."
|
||||||
git archive --format tar.gz -o $DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz $TRAVIS_TAG
|
git archive --format tar.gz -o "$DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz" "$TRAVIS_TAG"
|
||||||
|
|
||||||
# Change into the app directory
|
# Change into the app directory
|
||||||
cd $DIR/ffsend-$VERSION
|
cd -- "$DIR/ffsend-$VERSION"
|
||||||
|
|
||||||
# Build the debian package
|
# Build the debian package
|
||||||
# TODO: define GPG?
|
# TODO: define GPG?
|
||||||
dh_make -e "timvisee@gmail.com" -c gpl3 -f ffsend-$VERSION.tar.gz -s -y
|
dh_make -e "timvisee@gmail.com" -c gpl3 -f "ffsend-$VERSION.tar.gz" -s -y
|
||||||
rm *.ex README.Debian README.source
|
rm -- *.ex README.Debian README.source
|
||||||
|
|
||||||
# Remove the project tar ball, we're not using it anymore
|
# 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 the debian/control file
|
||||||
# TODO: configure copyright file
|
# TODO: configure copyright file
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
# Unlink the ffs alias if it links to ffsend
|
# Unlink the ffs alias if it links to ffsend
|
||||||
if [[ -L /usr/bin/ffs ]] \
|
if [[ -L /usr/bin/ffs ]] \
|
||||||
&& [[ $(ls -l /usr/bin/ffs | sed -e 's/.* -> //') == "/usr/bin/ffsend" ]]; \
|
&& [[ $(realpath /usr/bin/ffs) == "/usr/bin/ffsend" ]]; \
|
||||||
then
|
then
|
||||||
echo "Removing ffs alias for ffsend..."
|
echo "Removing ffs alias for ffsend..."
|
||||||
unlink /usr/bin/ffs
|
unlink /usr/bin/ffs
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"homepage": "https://github.com/timvisee/ffsend",
|
"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",
|
"license": "GPL-3.0-only",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"architecture": {
|
"architecture": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Ensure svg-term is installed
|
# Ensure svg-term is installed
|
||||||
if ! [ -x "$(command -v svg-term)" ]; then
|
if ! [ -x "$(command -v svg-term)" ]; then
|
||||||
|
|
|
@ -139,7 +139,7 @@ impl<'a> Download<'a> {
|
||||||
{
|
{
|
||||||
// Allocate an archive file, and update the download and target paths
|
// Allocate an archive file, and update the download and target paths
|
||||||
if extract {
|
if extract {
|
||||||
// TODO: select the extention dynamically
|
// TODO: select the extension dynamically
|
||||||
let archive_extention = ".tar";
|
let archive_extention = ".tar";
|
||||||
|
|
||||||
// Allocate a temporary file to download the archive to
|
// 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.
|
/// 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.
|
/// parent directories must be created.
|
||||||
///
|
///
|
||||||
/// The program will quit with an error message if a problem occurs.
|
/// The program will quit with an error message if a problem occurs.
|
||||||
|
@ -313,7 +313,7 @@ impl<'a> Download<'a> {
|
||||||
// Get the path string
|
// Get the path string
|
||||||
let path = target.to_str();
|
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);
|
let use_workdir = path.map(|path| path.trim().is_empty()).unwrap_or(true);
|
||||||
if use_workdir {
|
if use_workdir {
|
||||||
match current_dir() {
|
match current_dir() {
|
||||||
|
|
|
@ -24,7 +24,7 @@ impl<'a> Completions<'a> {
|
||||||
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
||||||
let matcher_completions = CompletionsMatcher::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 shells = matcher_completions.shells();
|
||||||
let dir = matcher_completions.output();
|
let dir = matcher_completions.output();
|
||||||
let quiet = matcher_main.quiet();
|
let quiet = matcher_main.quiet();
|
||||||
|
@ -38,14 +38,14 @@ impl<'a> Completions<'a> {
|
||||||
// Generate completions
|
// Generate completions
|
||||||
for shell in shells {
|
for shell in shells {
|
||||||
if !quiet {
|
if !quiet {
|
||||||
print!(
|
eprint!(
|
||||||
"Generating completions for {}...",
|
"Generating completions for {}...",
|
||||||
format!("{}", shell).to_lowercase()
|
format!("{}", shell).to_lowercase()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
app.gen_completions(crate_name!(), shell, &dir);
|
app.gen_completions(crate_name!(), shell, &dir);
|
||||||
if !quiet {
|
if !quiet {
|
||||||
println!(" done.");
|
eprintln!(" done.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ impl<'a> History<'a> {
|
||||||
|
|
||||||
// Remove history item
|
// Remove history item
|
||||||
if let Some(url) = matcher_history.rm() {
|
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) {
|
match history.remove_url(url) {
|
||||||
Ok(removed) if !removed => quit_error_msg(
|
Ok(removed) if !removed => quit_error_msg(
|
||||||
"could not remove item from history, no item matches given URL",
|
"could not remove item from history, no item matches given URL",
|
||||||
|
@ -120,11 +120,8 @@ impl<'a> History<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Define the cell values
|
// Define the cell values
|
||||||
let mut cells: Vec<String> = vec![
|
let mut cells: Vec<String> =
|
||||||
format!("{}", i + 1),
|
vec![format!("{}", i + 1), file.download_url(true).into(), expiry];
|
||||||
file.download_url(true).into_string(),
|
|
||||||
expiry,
|
|
||||||
];
|
|
||||||
if matcher_main.verbose() {
|
if matcher_main.verbose() {
|
||||||
cells.push(owner_token);
|
cells.push(owner_token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ fn select_api_version(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Propegate other errors
|
// Propagate other errors
|
||||||
Err(e) => return Err(e),
|
Err(e) => return Err(e),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::env::current_dir;
|
use std::env::current_dir;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io::Error as IoError;
|
use std::io::{Error as IoError, Write};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
#[cfg(feature = "archive")]
|
#[cfg(feature = "archive")]
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -19,7 +19,6 @@ use pathdiff::diff_paths;
|
||||||
use prettytable::{format::FormatBuilder, Cell, Row, Table};
|
use prettytable::{format::FormatBuilder, Cell, Row, Table};
|
||||||
#[cfg(feature = "qrcode")]
|
#[cfg(feature = "qrcode")]
|
||||||
use qr2term::print_qr;
|
use qr2term::print_qr;
|
||||||
#[cfg(feature = "archive")]
|
|
||||||
use tempfile::{Builder as TempBuilder, NamedTempFile};
|
use tempfile::{Builder as TempBuilder, NamedTempFile};
|
||||||
|
|
||||||
use super::select_api_version;
|
use super::select_api_version;
|
||||||
|
@ -36,7 +35,7 @@ use crate::urlshorten;
|
||||||
use crate::util::set_clipboard;
|
use crate::util::set_clipboard;
|
||||||
use crate::util::{
|
use crate::util::{
|
||||||
format_bytes, open_url, print_error, print_error_msg, prompt_yes, quit, quit_error_msg,
|
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.
|
/// A file upload action.
|
||||||
|
@ -57,20 +56,49 @@ impl<'a> Upload<'a> {
|
||||||
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();
|
||||||
let matcher_upload = UploadMatcher::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
|
// Get API parameters
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut paths: Vec<_> = matcher_upload
|
let mut paths: Vec<_> = files
|
||||||
.files()
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| Path::new(p).to_path_buf())
|
.map(|p| Path::new(p).to_path_buf())
|
||||||
.collect();
|
.collect();
|
||||||
let mut path = Path::new(paths.first().unwrap()).to_path_buf();
|
let mut path = Path::new(paths.first().unwrap()).to_path_buf();
|
||||||
let host = matcher_upload.host();
|
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
|
// All paths must exist
|
||||||
// TODO: ensure the file exists and is accessible
|
// TODO: ensure the file exists and is accessible
|
||||||
for path in &paths {
|
for path in &paths {
|
||||||
|
@ -196,7 +224,7 @@ impl<'a> Upload<'a> {
|
||||||
// Finish the archival process, writes the archive file
|
// Finish the archival process, writes the archive file
|
||||||
archiver.finish().map_err(ArchiveError::Write)?;
|
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 {
|
if let Some(ref mut file_name) = file_name {
|
||||||
file_name.push_str(archive_extention);
|
file_name.push_str(archive_extention);
|
||||||
}
|
}
|
||||||
|
@ -247,7 +275,7 @@ impl<'a> Upload<'a> {
|
||||||
// TODO: set false parameter to authentication state
|
// TODO: set false parameter to authentication state
|
||||||
let max_size = upload_size_max(api_version, auth);
|
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()) {
|
if let Ok(size) = path.metadata().map(|m| m.len()) {
|
||||||
// Enforce files not being 0 bytes
|
// Enforce files not being 0 bytes
|
||||||
if size == 0 && !matcher_main.force() {
|
if size == 0 && !matcher_main.force() {
|
||||||
|
@ -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")]
|
#[cfg(feature = "archive")]
|
||||||
{
|
{
|
||||||
// Close the temporary zip file, to ensure it's removed
|
// 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.
|
/// An error occurred while deleting a local file after upload.
|
||||||
#[fail(display = "failed to delete local file")]
|
#[fail(display = "failed to delete local file")]
|
||||||
Delete(#[cause] IoError),
|
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 {
|
impl From<VersionError> for Error {
|
||||||
|
|
|
@ -24,7 +24,7 @@ impl CmdArg for ArgApi {
|
||||||
.help("Server API version to use, '-' to lookup")
|
.help("Server API version to use, '-' to lookup")
|
||||||
.long_help(
|
.long_help(
|
||||||
"Server API version to use, one of:\n\
|
"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\
|
auto, -: probe server to determine\
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
|
|
|
@ -68,6 +68,7 @@ impl CmdArg for ArgDownloadLimit {
|
||||||
.alias("downloads")
|
.alias("downloads")
|
||||||
.alias("download")
|
.alias("download")
|
||||||
.value_name("COUNT")
|
.value_name("COUNT")
|
||||||
|
.env("FFSEND_DOWNLOAD_LIMIT")
|
||||||
.help("The file download limit")
|
.help("The file download limit")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
use chbs::{config::BasicConfig, prelude::*, word::WordList};
|
use chbs;
|
||||||
use clap::Arg;
|
use clap::Arg;
|
||||||
|
|
||||||
use super::{CmdArg, CmdArgFlag};
|
use super::{CmdArg, CmdArgFlag};
|
||||||
|
|
||||||
/// How many words the passphrase should consist of.
|
|
||||||
const PASSPHRASE_WORDS: usize = 5;
|
|
||||||
|
|
||||||
/// The passphrase generation argument.
|
/// The passphrase generation argument.
|
||||||
pub struct ArgGenPassphrase {}
|
pub struct ArgGenPassphrase {}
|
||||||
|
|
||||||
impl ArgGenPassphrase {
|
impl ArgGenPassphrase {
|
||||||
/// Generate a cryptographically secure passphrase that is easily
|
/// Generate a cryptographically secure passphrase that is easily
|
||||||
/// rememberable using diceware.
|
/// remembered using diceware.
|
||||||
pub fn gen_passphrase() -> String {
|
pub fn gen_passphrase() -> String {
|
||||||
let mut config = BasicConfig::default();
|
chbs::passphrase()
|
||||||
config.words = PASSPHRASE_WORDS;
|
|
||||||
config.word_provider = WordList::builtin_eff_general_short().sampler();
|
|
||||||
config.to_scheme().generate()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub mod owner;
|
||||||
pub mod password;
|
pub mod password;
|
||||||
pub mod url;
|
pub mod url;
|
||||||
|
|
||||||
// Re-eexport to arg module
|
// Re-export to arg module
|
||||||
pub use self::api::ArgApi;
|
pub use self::api::ArgApi;
|
||||||
pub use self::basic_auth::ArgBasicAuth;
|
pub use self::basic_auth::ArgBasicAuth;
|
||||||
pub use self::download_limit::ArgDownloadLimit;
|
pub use self::download_limit::ArgDownloadLimit;
|
||||||
|
|
|
@ -61,8 +61,8 @@ impl<'a: 'b, 'b> Handler<'a> {
|
||||||
let app = App::new(crate_name!())
|
let app = App::new(crate_name!())
|
||||||
.version(crate_version!())
|
.version(crate_version!())
|
||||||
.author(crate_authors!())
|
.author(crate_authors!())
|
||||||
.about(APP_ABOUT.as_ref())
|
.about(APP_ABOUT.as_str())
|
||||||
.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::GlobalVersion)
|
||||||
.global_setting(AppSettings::VersionlessSubcommands)
|
.global_setting(AppSettings::VersionlessSubcommands)
|
||||||
// TODO: enable below command when it doesn't break `p` anymore.
|
// 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")?;
|
let name = self.matches.value_of("name")?;
|
||||||
|
|
||||||
// The file name must not be empty
|
// 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() {
|
if name.trim().is_empty() {
|
||||||
quit_error_msg(
|
quit_error_msg(
|
||||||
"the file name must not be empty",
|
"the file name must not be empty",
|
||||||
|
@ -171,7 +171,7 @@ pub enum CopyMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn build(&self, url: &str) -> String {
|
||||||
match self {
|
match self {
|
||||||
CopyMode::Url => url.into(),
|
CopyMode::Url => url.into(),
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ffsend_api::{
|
||||||
url::Url,
|
url::Url,
|
||||||
};
|
};
|
||||||
use toml::{de::Error as DeError, ser::Error as SerError};
|
use toml::{de::Error as DeError, ser::Error as SerError};
|
||||||
use version_compare::{CompOp, VersionCompare};
|
use version_compare::Cmp;
|
||||||
|
|
||||||
use crate::util::{print_error, print_warning};
|
use crate::util::{print_error, print_warning};
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ const VERSION_MAX: &str = crate_version!();
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct History {
|
pub struct History {
|
||||||
/// The application version the history file was built with.
|
/// The application version the history file was built with.
|
||||||
/// Used for compatability checking.
|
/// Used for compatibility checking.
|
||||||
version: Option<String>,
|
version: Option<String>,
|
||||||
|
|
||||||
/// The file history.
|
/// The file history.
|
||||||
|
@ -62,9 +62,9 @@ impl History {
|
||||||
// Get the version number from the file
|
// Get the version number from the file
|
||||||
let version = history.version.as_ref().unwrap();
|
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");
|
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");
|
print_warning("history file has an unknown version, ignoring");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ impl History {
|
||||||
///
|
///
|
||||||
/// If the expiry property is None (thus unknown), the file will be kept.
|
/// 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 {
|
pub fn gc(&mut self) -> usize {
|
||||||
// Get a list of expired files
|
// Get a list of expired files
|
||||||
let expired: Vec<RemoteFile> = self
|
let expired: Vec<RemoteFile> = self
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub enum Error {
|
||||||
#[fail(display = "failed to shorten URL, got bad response")]
|
#[fail(display = "failed to shorten URL, got bad response")]
|
||||||
Response(#[cause] ResponseError),
|
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")]
|
#[fail(display = "failed to shorten URL, got malformed response")]
|
||||||
Malformed(#[cause] reqwest::Error),
|
Malformed(#[cause] reqwest::Error),
|
||||||
|
|
||||||
|
|
53
src/util.rs
53
src/util.rs
|
@ -11,11 +11,12 @@ use std::fmt;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
#[cfg(feature = "clipboard-bin")]
|
#[cfg(feature = "clipboard-bin")]
|
||||||
use std::io::ErrorKind as IoErrorKind;
|
use std::io::ErrorKind as IoErrorKind;
|
||||||
|
use std::io::{self, Read};
|
||||||
use std::io::{stderr, stdin, Error as IoError, Write};
|
use std::io::{stderr, stdin, Error as IoError, Write};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::{exit, ExitStatus};
|
use std::process::exit;
|
||||||
#[cfg(feature = "clipboard-bin")]
|
#[cfg(feature = "clipboard-bin")]
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
@ -290,14 +291,14 @@ pub fn highlight_info(msg: &str) -> ColoredString {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open the given URL in the users default browser.
|
/// Open the given URL in the users default browser.
|
||||||
/// The browsers exit statis is returned.
|
/// The browsers exit status is returned.
|
||||||
pub fn open_url(url: impl Borrow<Url>) -> Result<ExitStatus, IoError> {
|
pub fn open_url(url: impl Borrow<Url>) -> Result<(), IoError> {
|
||||||
open_path(url.borrow().as_str())
|
open_path(url.borrow().as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open the given path or URL using the program configured on the system.
|
/// Open the given path or URL using the program configured on the system.
|
||||||
/// The program exit statis is returned.
|
/// The program exit status is returned.
|
||||||
pub fn open_path(path: &str) -> Result<ExitStatus, IoError> {
|
pub fn open_path(path: &str) -> Result<(), IoError> {
|
||||||
open::that(path)
|
open::that(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,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
|
/// 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.
|
/// 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
|
/// 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.
|
/// flushed.
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
|
@ -490,7 +491,7 @@ pub enum ClipboardError {
|
||||||
#[fail(display = "failed to access clipboard using {}", _0)]
|
#[fail(display = "failed to access clipboard using {}", _0)]
|
||||||
BinaryIo(&'static str, #[cause] IoError),
|
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")]
|
#[cfg(feature = "clipboard-bin")]
|
||||||
#[fail(
|
#[fail(
|
||||||
display = "failed to use clipboard, {} exited with status code {}",
|
display = "failed to use clipboard, {} exited with status code {}",
|
||||||
|
@ -499,8 +500,8 @@ pub enum ClipboardError {
|
||||||
BinaryStatus(&'static str, i32),
|
BinaryStatus(&'static str, i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check for an emtpy password in the given `password`.
|
/// Check for an empty password in the given `password`.
|
||||||
/// If the password is emtpy the program will quit with an error unless
|
/// If the password is empty the program will quit with an error unless
|
||||||
/// forced.
|
/// forced.
|
||||||
// TODO: move this to a better module
|
// TODO: move this to a better module
|
||||||
pub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {
|
pub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {
|
||||||
|
@ -518,7 +519,7 @@ pub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {
|
||||||
|
|
||||||
/// Prompt the user to enter a password.
|
/// 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> {
|
pub fn prompt_password(main_matcher: &MainMatcher, optional: bool) -> Option<String> {
|
||||||
// Quit with an error if we may not interact
|
// Quit with an error if we may not interact
|
||||||
if !optional && main_matcher.no_interact() {
|
if !optional && main_matcher.no_interact() {
|
||||||
|
@ -548,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) => {
|
Err(err) => {
|
||||||
if !optional {
|
if !optional {
|
||||||
quit_error(
|
quit_error(
|
||||||
|
@ -591,7 +592,7 @@ pub fn ensure_password(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whehter we allow interaction
|
// Check whether we allow interaction
|
||||||
let interact = !main_matcher.no_interact();
|
let interact = !main_matcher.no_interact();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -760,7 +761,7 @@ pub fn ensure_owner_token(
|
||||||
main_matcher: &MainMatcher,
|
main_matcher: &MainMatcher,
|
||||||
optional: bool,
|
optional: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// Check whehter we allow interaction
|
// Check whether we allow interaction
|
||||||
let interact = !main_matcher.no_interact();
|
let interact = !main_matcher.no_interact();
|
||||||
|
|
||||||
// Notify that an owner token is required
|
// Notify that an owner token is required
|
||||||
|
@ -983,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 {
|
if space >= size {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1131,3 +1132,27 @@ pub fn rand_alphanum_string(len: usize) -> String {
|
||||||
.take(len)
|
.take(len)
|
||||||
.collect()
|
.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
Add a link
Reference in a new issue