[
  {
    "path": ".gitattributes",
    "content": "# Mark generated completion files as vendored\ncontrib/completions/* linguist-vendored\ncontrib/completions/gen_completions linguist-vendored=false\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# Funding links\ngithub:\n  - timvisee\ncustom:\n  - \"https://timvisee.com/donate\"\npatreon: timvisee\nko_fi: timvisee\n"
  },
  {
    "path": ".gitignore",
    "content": ".*.sw[po]\ntarget/\n**/*.rs.bk\n.idea/\nsnapcraft.login\n"
  },
  {
    "path": ".gitlab-ci.yml",
    "content": "# GitLab CI configuration for ffsend builds, tests and releases\n#\n# To add a new release:\n# - configure a new 'build-*' job with the proper target\n# - export a build artifact from the new job\n# - manually upload artifact to GitHub in the 'github-release' job\n\nimage: \"rust:slim-bookworm\"\n\nstages:\n  - check\n  - build\n  - test\n  - release\n  - package\n\n# Variable defaults\nvariables:\n  RUST_VERSION: stable\n  RUST_TARGET: x86_64-unknown-linux-gnu\n\n# Cache rust/cargo/build artifacts\ncache:\n  key: \"$CI_PIPELINE_ID-$RUST_VERSION\"\n  paths:\n    - /usr/local/cargo/registry/\n    - /usr/local/rustup/toolchains/\n    - /usr/local/rustup/update-hashes/\n    - target/\n\n# Install compiler and OpenSSL dependencies\nbefore_script:\n  - apt-get update\n  - apt-get install -y --no-install-recommends build-essential pkg-config libssl-dev\n  - |\n    rustup install $RUST_VERSION\n    rustup default $RUST_VERSION\n  - |\n    rustc --version\n    cargo --version\n\n# Check on stable, beta and nightly\n.check-base: &check-base\n  stage: check\n  script:\n    - cargo check --verbose\n    - cargo check --no-default-features --features send3,crypto-ring --verbose\n    - cargo check --no-default-features --features send2,crypto-openssl --verbose\n    - cargo check --no-default-features --features send3,crypto-openssl --verbose\n    - cargo check --no-default-features --features send2,send3,crypto-openssl --verbose\n    - cargo check --no-default-features --features send3,crypto-ring,archive --verbose\n    - cargo check --no-default-features --features send3,crypto-ring,history --verbose\n    - cargo check --no-default-features --features send3,crypto-ring,qrcode --verbose\n    - cargo check --no-default-features --features send3,crypto-ring,urlshorten --verbose\n    - cargo check --no-default-features --features send3,crypto-ring,infer-command --verbose\n    - cargo check --features no-color --verbose\ncheck-stable:\n  <<: *check-base\ncheck-beta:\n  <<: *check-base\n  variables:\n    RUST_VERSION: beta\ncheck-nightly:\n  <<: *check-base\n  variables:\n    RUST_VERSION: nightly\ncheck-msrv:\n  <<: *check-base\n  variables:\n    RUST_VERSION: \"1.63.0\"\n\n# Build using Rust stable\nbuild-x86_64-linux-gnu:\n  stage: build\n  needs: []\n  script:\n    - cargo build --target=$RUST_TARGET --release --verbose\n    - mv target/$RUST_TARGET/release/ffsend ./ffsend-$RUST_TARGET\n    - strip -g ./ffsend-$RUST_TARGET\n  artifacts:\n    name: ffsend-x86_64-linux-gnu\n    paths:\n      - ffsend-$RUST_TARGET\n    expire_in: 1 month\n\n# Build a static version\nbuild-x86_64-linux-musl:\n  stage: build\n  needs: []\n  variables:\n    RUST_TARGET: x86_64-unknown-linux-musl\n  script:\n    # Install the static target\n    - rustup target add $RUST_TARGET\n\n    # Build OpenSSL statically\n    - apt-get install -y build-essential wget musl-tools\n    - wget https://github.com/openssl/openssl/releases/download/openssl-3.0.15/openssl-3.0.15.tar.gz\n    - tar xzvf openssl-3.0.15.tar.gz\n    - cd openssl-3.0.15\n    - ./config no-async -fPIC --openssldir=/usr/local/ssl --prefix=/usr/local\n    - make\n    - make install\n    - cd ..\n\n    # Statically build ffsend\n    - export OPENSSL_STATIC=1\n    - export OPENSSL_LIB_DIR=/usr/local/lib64\n    - export OPENSSL_INCLUDE_DIR=/usr/local/include\n    - cargo build --target=$RUST_TARGET --release --verbose\n\n    # Prepare the release artifact, strip it\n    - find . -name ffsend -exec ls -lah {} \\;\n    - mv target/$RUST_TARGET/release/ffsend ./ffsend-$RUST_TARGET\n    - strip -g ./ffsend-$RUST_TARGET\n  artifacts:\n    name: ffsend-x86_64-linux-musl\n    paths:\n      - ffsend-$RUST_TARGET\n    expire_in: 1 month\n\n# Run the unit tests through Cargo\ntest-cargo:\n  stage: test\n  needs: []\n  dependencies: []\n  script:\n    - cargo test --verbose\n\n# Run integration test with the public Send service\ntest-public:\n  image: alpine:latest\n  stage: test\n  dependencies:\n    - build-x86_64-linux-musl\n  variables:\n    GIT_STRATEGY: none\n    RUST_TARGET: x86_64-unknown-linux-musl\n  before_script: []\n  script:\n    # Prepare ffsend binary, create random file\n    - mv ./ffsend-$RUST_TARGET ./ffsend\n    - chmod a+x ./ffsend\n    - head -c1m </dev/urandom >test.txt\n\n    # Generate random file, upload/download and assert equality\n    - ./ffsend upload test.txt -I\n    - ./ffsend download $(./ffsend history -q) -I -o=download.txt\n    - \"cmp -s ./test.txt ./download.txt || (echo ERROR: Downloaded file is different than original; exit 1)\"\n    - rm ./download.txt\n\n# Cargo crate release\nrelease-crate:\n  stage: release\n  dependencies: []\n  only:\n    - /^v(\\d+\\.)*\\d+$/\n  script:\n    - echo \"Creating release crate to publish on crates.io...\"\n    - echo $CARGO_TOKEN | cargo login\n    - echo \"Publishing crate to crates.io...\"\n    - cargo publish --verbose --allow-dirty\n\n# Snap release\nrelease-snap:\n  image: snapcore/snapcraft:stable\n  stage: release\n  dependencies: []\n  only:\n    - /^v(\\d+\\.)*\\d+$/\n  before_script: []\n  script:\n    # Prepare the environment\n    - apt-get update -y\n    - apt-get install python3 -yqq\n    - cd pkg/snap\n\n    # Update version number in snapcraft.yaml\n    - VERSION=$(echo $CI_COMMIT_REF_NAME | cut -c 2-)\n    - echo \"Determined binary version number 'v$VERSION', updating snapcraft.yaml...\"\n    - 'sed \"s/^version:.*\\$/version: $VERSION/\" -i snapcraft.yaml'\n    - 'sed \"s/^pkgver=.*\\$/pkgver=$VERSION/\" -i snapcraft.yaml'\n\n    # Build the package\n    - echo \"Building snap package...\"\n    - snapcraft\n\n    # Publish snap package\n    - echo \"Publishing snap package...\"\n    - snapcraft whoami\n    - snapcraft push --release=stable ffsend_*_amd64.snap\n  artifacts:\n    name: ffsend-snap-x86_64\n    paths:\n      - pkg/snap/ffsend_*_amd64.snap\n    expire_in: 1 month\n\n# Publish release binaries to as GitHub release\nrelease-github:\n  stage: release\n  only:\n    - /^v(\\d+\\.)*\\d+$/\n  dependencies:\n    - build-x86_64-linux-gnu\n    - build-x86_64-linux-musl\n  before_script: []\n  script:\n    # Install dependencies\n    - apt-get update\n    - apt-get install -y curl wget gzip netbase\n\n    # Download github-release binary\n    - wget https://github.com/tfausak/github-release/releases/download/1.2.5/github-release-linux.gz -O github-release.gz\n    - gunzip github-release.gz\n    - chmod a+x ./github-release\n\n    # Create the release, upload binaries\n    - ./github-release release --token \"$GITHUB_TOKEN\" --owner timvisee --repo ffsend --tag \"$CI_COMMIT_REF_NAME\"  --title \"ffsend $CI_COMMIT_REF_NAME\"\n    - ./github-release upload --token \"$GITHUB_TOKEN\" --owner timvisee --repo ffsend --tag \"$CI_COMMIT_REF_NAME\" --file ./ffsend-x86_64-unknown-linux-gnu --name ffsend-$CI_COMMIT_REF_NAME-linux-x64\n    - ./github-release upload --token \"$GITHUB_TOKEN\" --owner timvisee --repo ffsend --tag \"$CI_COMMIT_REF_NAME\" --file ./ffsend-x86_64-unknown-linux-musl --name ffsend-$CI_COMMIT_REF_NAME-linux-x64-static\n\n# Publish a Docker image\nrelease-docker:\n  image: docker:git\n  stage: release\n  only:\n    - /^v(\\d+\\.)*\\d+$/\n  dependencies:\n    - build-x86_64-linux-musl\n  services:\n    - docker:dind\n  variables:\n    RUST_TARGET: x86_64-unknown-linux-musl\n    DOCKER_HOST: tcp://docker:2375\n    # DOCKER_DRIVER: overlay2\n  before_script: []\n  script:\n    # Place binary in Docker directory, change to it\n    - mv ./ffsend-$RUST_TARGET ./pkg/docker/ffsend\n    - cd ./pkg/docker\n\n    # Build the Docker image, run it once to test\n    - docker build -t timvisee/ffsend:latest ./\n    - docker run --rm timvisee/ffsend:latest -V\n\n    # Retag version\n    - VERSION=$(echo $CI_COMMIT_REF_NAME | cut -c 2-)\n    - echo \"Determined Docker image version number 'v$VERSION', retagging image...\"\n    - docker tag timvisee/ffsend:latest timvisee/ffsend:$VERSION\n\n    # Authenticate and push the Docker images\n    - echo \"$DOCKER_PASSWORD\" | docker login -u \"$DOCKER_USER\" --password-stdin\n    - docker push timvisee/ffsend:$VERSION\n    - docker push timvisee/ffsend:latest\n\n# AUR packages release\npackage-aur:\n  image: archlinux\n  stage: package\n  needs:\n    - release-github\n  dependencies: []\n  only:\n    - /^v(\\d+\\.)*\\d+$/\n  before_script: []\n  script:\n    - cd ./pkg/aur\n\n    # Determine the version number we're releasing for\n    - VERSION=$(echo $CI_COMMIT_REF_NAME | cut -c 2-)\n    - echo \"Determined binary version number 'v$VERSION'\"\n\n    # Determine remote URLs and SHA checksums\n    - echo \"Determining SHA checksums for remote files...\"\n    - URL_BIN=https://github.com/timvisee/ffsend/releases/download/v$VERSION/ffsend-v$VERSION-linux-x64-static\n    - URL_SOURCE=https://gitlab.com/timvisee/ffsend/-/archive/v$VERSION/ffsend-v$VERSION.tar.gz\n    - URL_BASH_COMPLETION=https://gitlab.com/timvisee/ffsend/raw/v$VERSION/contrib/completions/ffsend.bash\n    - URL_ZSH_COMPLETION=https://gitlab.com/timvisee/ffsend/raw/v$VERSION/contrib/completions/_ffsend\n    - URL_FISH_COMPLETION=https://gitlab.com/timvisee/ffsend/raw/v$VERSION/contrib/completions/ffsend.fish\n    - URL_LICENSE=https://gitlab.com/timvisee/ffsend/raw/v$VERSION/LICENSE\n    - 'echo \"Selected binary URL: $URL_BIN\"'\n    - 'echo \"Selected source URL: $URL_SOURCE\"'\n    - echo \"Determining sha256sum for remote binary...\"\n    - 'SHA_BIN=$(curl -sSL \"$URL_BIN\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sum: $SHA_BIN\"'\n    - 'SHA_BASH_COMPLETION=$(curl -sSL \"$URL_BASH_COMPLETION\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sums of bash completion: $SHA_BASH_COMPLETION\"'\n    - 'SHA_ZSH_COMPLETION=$(curl -sSL \"$URL_ZSH_COMPLETION\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sums of ZSH completion: $SHA_ZSH_COMPLETION\"'\n    - 'SHA_FISH_COMPLETION=$(curl -sSL \"$URL_FISH_COMPLETION\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sums of fish completion: $SHA_FISH_COMPLETION\"'\n    - 'SHA_LICENSE=$(curl -sSL \"$URL_LICENSE\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sums of LICENSE: $SHA_LICENSE\"'\n    - echo \"Determining sha256sum for remote source...\"\n    - 'SHA_SOURCE=$(curl -sSL \"$URL_SOURCE\" | sha256sum | cut -d\" \" -f1)'\n    - 'echo \"Got sha256sum: $SHA_SOURCE\"'\n\n    # Update PKGBUILD parameters: version, source URL and SHA sum\n    - echo \"Updating PKGBUILDS with release information...\"\n    - sed \"s/^pkgver=.*\\$/pkgver=$VERSION/\" -i ffsend/PKGBUILD\n    - sed \"s/^pkgver=.*\\$/pkgver=$VERSION/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/^pkgver=.*\\$/pkgver=$VERSION.$CI_COMMIT_SHORT_SHA/\" -i ffsend-git/PKGBUILD\n    - sed \"s/^source=(\\\".*\\\").*\\$/source=(\\\"$(echo $URL_SOURCE | sed 's/\\//\\\\\\//g')\\\")/\" -i ffsend/PKGBUILD\n    - sed \"s/\\(\\\"ffsend-v\\$pkgver::\\).*\\\"/\\1$(echo $URL_BIN | sed 's/\\//\\\\\\//g')\\\"/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/\\(\\\"ffsend-v\\$pkgver.bash::\\).*\\\"/\\1$(echo $URL_BASH_COMPLETION | sed 's/\\//\\\\\\//g')\\\"/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/\\(\\\"ffsend-v\\$pkgver.zsh::\\).*\\\"/\\1$(echo $URL_ZSH_COMPLETION | sed 's/\\//\\\\\\//g')\\\"/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/\\(\\\"ffsend-v\\$pkgver.fish::\\).*\\\"/\\1$(echo $URL_FISH_COMPLETION | sed 's/\\//\\\\\\//g')\\\"/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/\\(\\\"LICENSE-v\\$pkgver::\\).*\\\"/\\1$(echo $URL_LICENSE | sed 's/\\//\\\\\\//g')\\\"/\" -i ffsend-bin/PKGBUILD\n    - sed \"s/^sha256sums=.*\\$/sha256sums=('$SHA_SOURCE')/\" -i ffsend/PKGBUILD\n    - sed \"s/^sha256sums=.*\\$/sha256sums=('$SHA_BIN' '$SHA_BASH_COMPLETION' '$SHA_ZSH_COMPLETION' '$SHA_FISH_COMPLETION' '$SHA_LICENSE')/\" -i ffsend-bin/PKGBUILD\n\n    # Get SHA hash for local and remote file w/o version, update if it has changed\n    - 'SHA_STRIP_LOCAL=$(cat ffsend-git/PKGBUILD | sed /^pkgver=.\\*/d | sha256sum | cut -d\" \" -f1)'\n    - 'SHA_STRIP_REMOTE=$(curl -sSL \"https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD?h=ffsend-git\" | sed /^pkgver=.\\*/d | sha256sum | cut -d\" \" -f1)'\n\n    # Install dependencies\n    - echo \"Installing required build packages...\"\n    - pacman -Syu --noconfirm sudo base-devel binutils openssh rust cargo cmake git openssl\n\n    # Make AUR package\n    - mkdir -p /.cargo\n    - chmod -R 777 /.cargo\n    - cd ffsend-bin/\n    - echo \"Making binary package...\"\n    - sudo -u nobody makepkg -c\n    - sudo -u nobody makepkg --printsrcinfo > .SRCINFO\n    - cd ../ffsend\n    - echo \"Making main source package...\"\n    - sudo -u nobody makepkg -c\n    - sudo -u nobody makepkg --printsrcinfo > .SRCINFO\n    # Make git package if different than the remote\n    - |\n      if [ ! \"$SHA_STRIP_LOCAL\" == \"$SHA_STRIP_REMOTE\" ]; then\n        cd ../ffsend-git\n        echo \"Making git source package...\"\n        sudo -u nobody makepkg -c\n        sudo -u nobody makepkg --printsrcinfo > .SRCINFO\n      else\n        echo \"Not making git source package, it has not changed\"\n      fi\n    - cd ..\n\n    # Set up SSH for publishing\n    - mkdir -p /root/.ssh\n    - cp ./aur.pub /root/.ssh/id_rsa.pub\n    - echo \"$AUR_SSH_PRIVATE\" > /root/.ssh/id_rsa\n    - echo \"Host aur.archlinux.org\" >> /root/.ssh/config\n    - echo \"  IdentityFile /root/.ssh/aur\" >> /root/.ssh/config\n    - echo \"  User aur\" >> /root/.ssh/config\n    - chmod 600 /root/.ssh/{id_rsa*,config}\n    - eval `ssh-agent -s`\n    - ssh-add /root/.ssh/id_rsa\n    - ssh-keyscan -H aur.archlinux.org >> /root/.ssh/known_hosts\n    - git config --global user.name \"timvisee\"\n    - git config --global user.email \"tim@visee.me\"\n\n    # Publish main package: clone AUR repo, commit update and push\n    - git clone ssh://aur@aur.archlinux.org/ffsend.git aur-ffsend\n    - cd aur-ffsend\n    - cp ../ffsend/{PKGBUILD,.SRCINFO} ./\n    - git add PKGBUILD .SRCINFO\n    - git commit -m \"Release v$VERSION\"\n    - git push\n    - cd ..\n\n    # Publish binary package: clone AUR repo, commit update and push\n    - git clone ssh://aur@aur.archlinux.org/ffsend-bin.git aur-ffsend-bin\n    - cd aur-ffsend-bin\n    - cp ../ffsend-bin/{PKGBUILD,.SRCINFO} ./\n    - git add PKGBUILD .SRCINFO\n    - git commit -m \"Release v$VERSION\"\n    - git push\n    - cd ..\n\n    # Publish git package: clone AUR repo, commit update and push\n    # Only publish it if it is different than the remote\n    - |\n      if [ ! \"$SHA_STRIP_LOCAL\" == \"$SHA_STRIP_REMOTE\" ]; then\n        git clone ssh://aur@aur.archlinux.org/ffsend-git.git aur-ffsend-git\n        cd aur-ffsend-git\n        cp ../ffsend-git/{PKGBUILD,.SRCINFO} ./\n        git add PKGBUILD .SRCINFO\n        git commit -m \"Update PKGBUILD for release v$VERSION\"\n        git push\n        cd ..\n      else\n        echo \"Not pushing git package, it has not changed\"\n      fi\n\n# TODO: add job to test ffsend{-git} AUR packages\n"
  },
  {
    "path": ".travis.yml",
    "content": "# Travis CI configuration for building macOS binaries for ffsend.\n# These macOS binaries are published on GitHub as release files.\n#\n# The main CI runs on GitLab CI at: https://gitlab.com/timvisee/ffsend/pipelines\n\nlanguage: rust\n\n# Only build release jobs\nstages:\n  - name: release\n    if: tag =~ ^v(\\d+\\.)*\\d+$\n\njobs:\n  include:\n    - stage: release\n      rust: stable\n      os: osx\n      env: RUST_TARGET=x86_64-apple-darwin\n      cache: cargo\n      script:\n        # Create release binary for macOS\n        - echo \"Creating release binary for $RUST_TARGET...\"\n        - cargo build --target=$RUST_TARGET --release --verbose --all\n        - cp target/$RUST_TARGET/release/ffsend ./ffsend\n\n        # Download github-release binary\n        - wget https://github.com/tfausak/github-release/releases/download/1.2.4/github-release-osx.gz -O github-release.gz\n        - gunzip github-release.gz\n        - chmod a+x ./github-release\n\n        # Create the release, upload binary\n        - ./github-release release --token \"$GITHUB_TOKEN\" --owner timvisee --repo ffsend --tag \"$TRAVIS_TAG\"  --title \"ffsend $TRAVIS_TAG\"\n        - ./github-release upload --token \"$GITHUB_TOKEN\" --owner timvisee --repo ffsend --tag \"$TRAVIS_TAG\" --file ./ffsend --name ffsend-$TRAVIS_TAG-macos\n\n        # TODO: disabled for now to throttle updates, manually enable on major release\n        # # Update homebrew package\n        # - git config --global user.name \"timvisee\"\n        # - git config --global user.email \"$GIT_EMAIL\"\n        # - git config --global credential.helper store\n        # - echo \"https://timvisee:$HOMEBREW_GITHUB_API_TOKEN@github.com\" >> ~/.git-credentials\n        # - brew bump-formula-pr --url=\"https://github.com/timvisee/ffsend/archive/$TRAVIS_TAG.tar.gz\" --message=\"Automated release pull request using continuous integration.\" --no-browse -f -v ffsend\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\n**Repository:**\n- [GitLab repository][gitlab]\n- _Mirror: [GitHub repository][github]_\n\n**Issues:** (bug reporting, feature requests, enhancements, etc.)\n- [GitLab issue board][gitlab-issues]\n- _Alternatively: [GitHub issue board][github-issues]_\n\n**Pull/merge requests:** (fixes, implemented features, etc.)\n- [GitLab merge requests][gitlab-mr]\n- _Alternatively: [GitHub pull requests][github-pr]_\n\n\n\nContributions to the `ffsend` project are welcome!\nWhen contributing new features, alternative implementations or bigger\nimprovements, please first discuss the change you wish to make via an issue\nor email.\nSmall changes such as fixed commands, fixed spelling or dependency updates\nare always welcome without discussion.\n\nThe `ffsend` repository is primarily hosted on [GitLab][gitlab].\n[GitHub][github] hosts a mirror, for publicity and findability.\nPlease open any issues or pull requests on the [GitLab][gitlab] pages if possible.\nOtherwise opening these on [GitHub][github] is fine, though they might be\nmanually moved over to [GitLab][gitlab].\n\nPlease note we have a code of conduct, please follow it in all your interactions\nwith the project.\n\n## Pull Request Process\n\n1. Ensure you've discussed your improvements in an issue when working on a\n   bigger change\n2. Ensure your branch is up-to-date with the latest [`master`][branch-master]\n3. Ensure the project builds with your changes: `cargo build`\n4. Ensure the project tests succeed with your changes: `cargo test`\n5. Update the `README.md` with details of significant changes, this includes new\n   compiler features, command-line arguments, environment variables or new\n   package installation instructions.\n6. Submit your pull request.\n7. Fix any issues continuous integration might report.\n\nAdditional notes:\n- Do not change version numbers, this is done by @timvisee\n\n## Code of Conduct\n\n### Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, gender identity and expression, level of experience,\nnationality, personal appearance, race, religion, or sexual identity and\norientation.\n\n### Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\nadvances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n### Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n### Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n### Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project owner at 3a4fb3964f@sinenomine.email. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n### Attribution\nThis Code of Conduct is adapted from the [Contributor Covenant][coc-homepage], version 1.4,\navailable at [https://contributor-covenant.org/version/1/4][coc-version]\n\n## License\nThis project is released under the GNU GPL-3.0 license.\nCheck out the [LICENSE](LICENSE) file for more information.\n\n[branch-master]: https://gitlab.com/timvisee/ffsend/tree/master\n[gitlab]: https://gitlab.com/timvisee/ffsend\n[gitlab-issues]: https://gitlab.com/timvisee/ffsend/issues\n[gitlab-mr]: https://gitlab.com/timvisee/ffsend/merge_requests\n[github]: https://github.com/timvisee/ffsend\n[github-issues]: https://github.com/timvisee/ffsend/issues\n[github-pr]: https://github.com/timvisee/ffsend/pulls\n[coc-homepage]: https://contributor-covenant.org\n[coc-version]: https://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"ffsend\"\nversion = \"0.2.77\"\nrust-version = \"1.63.0\"\nauthors = [\"Tim Visee <3a4fb3964f@sinenomine.email>\"]\nlicense = \"GPL-3.0\"\nreadme = \"README.md\"\nhomepage = \"https://timvisee.com/projects/ffsend\"\nrepository = \"https://gitlab.com/timvisee/ffsend\"\ndescription = \"\"\"\\\n    Easily and securely share files from the command line.\\n\\\n    A fully featured Send client.\\\n\"\"\"\nkeywords = [\"send\", \"firefox\", \"cli\"]\ncategories = [\n    \"authentication\",\n    \"command-line-interface\",\n    \"command-line-utilities\",\n    \"cryptography\",\n    \"network-programming\",\n]\nexclude = [\n    \"/.github\",\n    \"/contrib\",\n    \"/pkg\",\n    \"/res\",\n    \"/*.yml\",\n    \"/CONTRIBUTING.md\",\n    \"/SECURITY.md\",\n]\nedition = \"2018\"\nbuild = \"build.rs\"\n\n[package.metadata.deb]\nsection = \"utility\"\nextended-description = \"\"\"\\\nEasily and securely share files and directories from the command line through\na safe, private and encrypted link using a single simple command. \\\nFiles are shared using the Send service and may be up to 2GB. \\\nOthers are able to download these files with this tool, \\\nor through their web browser.\\n\\\n\\n\\\nAll files are always encrypted on the client, \\\nand secrets are never shared with the remote host. \\\nAn optional password may be specified, and a default file lifetime of 1 \\\n(up to 20) download or 24 hours is enforced to ensure your stuff does not \\\nremain online forever. This provides a secure platform to share your files.\"\"\"\npriority = \"standard\"\nlicense-file = [\"LICENSE\", \"3\"]\ndepends = \"$auto, libssl1.1, ca-certificates, xclip\"\nmaintainer-scripts = \"pkg/deb\"\n\n[[bin]]\nname = \"ffsend\"\npath = \"src/main.rs\"\n\n[features]\ndefault = [\"archive\", \"clipboard\", \"crypto-ring\", \"history\", \"infer-command\", \"qrcode\", \"send3\", \"urlshorten\"]\n\n# Compile with file archiving support\narchive = [\"tar\"]\n\n# Support for putting share URLs in clipboard\nclipboard = [\"clip\", \"which\"]\n\n# Compile with file history support\nhistory = []\n\n# Support for Send v2\nsend2 = [\"ffsend-api/send2\"]\n\n# Support for Send v3\nsend3 = [\"ffsend-api/send3\"]\n\n# Use OpenSSL as cryptography backend\ncrypto-openssl = [\"ffsend-api/crypto-openssl\"]\n\n# Use ring as cryptography backend\ncrypto-ring = [\"ffsend-api/crypto-ring\"]\n\n# Support for generating QR codes for share URLs\nqrcode = [\"qr2term\"]\n\n# Support for shortening share URLs\nurlshorten = [\"urlshortener\"]\n\n# Support for inferring subcommand when linking binary\ninfer-command = []\n\n# Compile without colored output support\nno-color = [\"colored/no-color\"]\n\n# Automatic using build.rs: use xclip/xsel binary method for clipboard support\nclipboard-bin = [\"clipboard\"]\n\n# Automatic using build.rs: use native clipboard crate for clipboard support\nclipboard-crate = [\"clipboard\"]\n\n[dependencies]\nchbs = \"0.1.0\"\nchrono = \"0.4\"\nclap = \"2.33\"\ncolored = \"2.0\"\nderive_builder = \"0.10\"\ndirectories = \"4.0\"\nfailure = \"0.1\"\nffsend-api = { version = \"0.7.3\", default-features = false }\nfs2 = \"0.4\"\nlazy_static = \"1.4\"\nopen = \"2\"\nopenssl-probe = \"0.1\"\npathdiff = \"0.2\"\npbr = \"1\"\nprettytable-rs = { version = \"0.10.0\", default-features = false }\nqr2term = { version = \"0.2\", optional = true }\nrand = \"0.8\"\nregex = \"1.5\"\nrpassword = \"5\"\nserde = \"1\"\nserde_derive = \"1\"\ntar = { version = \"0.4\", optional = true }\ntempfile = \"3\"\ntoml = \"0.5\"\nurlshortener = { version = \"3\", optional = true }\nversion-compare = \"0.1\"\n\n[target.'cfg(any(target_os = \"linux\", target_os = \"freebsd\", target_os = \"dragonfly\", target_os = \"openbsd\", target_os = \"netbsd\"))'.dependencies]\nwhich = { version = \"4.0\", optional = true }\n\n[target.'cfg(not(any(target_os = \"linux\", target_os = \"freebsd\", target_os = \"dragonfly\", target_os = \"openbsd\", target_os = \"netbsd\")))'.dependencies]\n# Aliased to clip to prevent name collision with clipboard feature\nclip = { version = \"0.5\", optional = true, package = \"clipboard\" }\n\n[package.metadata.docs.rs]\ntargets = [\"x86_64-unknown-linux-gnu\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "[![Build status on GitLab CI][gitlab-ci-master-badge]][gitlab-ci-link]\n[![Newest release on crates.io][crate-version-badge]][crate-link]\n[![Project license][crate-license-badge]](LICENSE)\n\n[crate-license-badge]: https://img.shields.io/crates/l/ffsend.svg\n[crate-link]: https://crates.io/crates/ffsend\n[crate-version-badge]: https://img.shields.io/crates/v/ffsend.svg\n[gitlab-ci-link]: https://gitlab.com/timvisee/ffsend/pipelines\n[gitlab-ci-master-badge]: https://gitlab.com/timvisee/ffsend/badges/master/pipeline.svg\n\n*Notice: the default Send host is provided by [@timvisee][timvisee]\n([info](https://gitlab.com/timvisee/ffsend/-/issues/111)).\nPlease consider to [donate] and help keep it running.*\n\n# ffsend\n\n> Easily and securely share files from the command line.\n> A [Send][send] client.\n\nEasily and securely share files and directories from the command line through a\nsafe, private and encrypted link using a single simple command.\nFiles are shared using the [Send][send] service and may be up\nto 1GB. Others are able to download these files with this tool, or through\ntheir web browser.\n\n[![ffsend usage demo][usage-demo-svg]][usage-demo-asciinema]  \n_No demo visible here? View it on [asciinema][usage-demo-asciinema]._\n\nAll files are always encrypted on the client, and secrets are never shared with\nthe remote host. An optional password may be specified, and a default file\nlifetime of 1 (up to 20) download or 24 hours is enforced to ensure your stuff\ndoes not remain online forever.\nThis provides a secure platform to share your files.\nFind out more about security [here](#security).\n\n- [Features](#features)\n- [Usage](#usage)\n- [Requirements](#requirements)\n- [Install](#install) ([Linux](#linux-all-distributions), [macOS](#macos), [Windows](#windows), [FreeBSD](#freebsd), [Android](#android), [_Other OS/architecture_](#other-os-or-architecture))\n- [Build](#build)\n- [Configuration and environment](#configuration-and-environment)\n- [Security](#security)\n- [Help](#help)\n- [Special thanks](#special-thanks)\n- [License](#license)\n\nThe public [Send][send] service that is used as default host is provided by\n[@timvisee][timvisee] ([info](https://gitlab.com/timvisee/ffsend/-/issues/111)).  \nThis application is not affiliated with [Firefox][firefox] or\n[Mozilla][mozilla] in any way.\n\n_Note: this tool is currently in beta, as some extra desired features are yet to be implemented_\n\n## Features\n- Fully featured and friendly command line tool\n- Upload and download files and directories securely, always encrypted on the client\n- Additional password protection, generation and configurable download limits\n- File and directory archiving and extraction\n- Built-in share URL shortener and QR code generator\n- Supports Send v3 (current) and v2\n- History tracking your files for easy management\n- Ability to use your own Send hosts\n- Inspect or delete shared files\n- Accurate error reporting\n- Streaming encryption and uploading/downloading, very low memory footprint\n- Intended for use in [scripts](#scriptability) without interaction\n\nFor a list of upcoming features and ideas, take a look at the\ncurrent [open issues](https://gitlab.com/timvisee/ffsend/issues) over on GitLab.\n\n## Usage\nEasily upload and download:\n\n```bash\n# Simple upload\n$ ffsend upload my-file.txt\nhttps://send.vis.ee/#sample-share-url\n\n# Advanced upload\n# - Specify a download limit of 1\n# - Specify upload expiry time of 5 minutes\n# - Enter a password to encrypt the file\n# - Archive the file before uploading\n# - Copy the shareable link to your clipboard\n# - Open the shareable link in your browser\n$ ffsend upload --downloads 1 --expiry-time 5m --password --archive --copy --open my-file.txt\nPassword: ******\nhttps://send.vis.ee/#sample-share-url\n\n# Upload to your own host\n$ ffsend u -h https://example.com/ my-file.txt\nhttps://example.com/#sample-share-url\n\n# Simple download\n$ ffsend download https://send.vis.ee/#sample-share-url\n```\n\nInspect remote files:\n\n```bash\n# Check if a file exists\n$ ffsend exists https://send.vis.ee/#sample-share-url\nExists: yes\n\n# Fetch remote file info\n$ ffsend info https://send.vis.ee/#sample-share-url\nID:         b087066715\nName:       my-file.txt\nSize:       12 KiB\nMIME:       text/plain\nDownloads:  0 of 10\nExpiry:     18h2m (64928s)\n```\n\nOther commands include:\n\n```bash\n# View your file history\n$ ffsend history\n#  LINK                                        EXPIRE\n1  https://send.vis.ee/#sample-share-url  23h57m\n2  https://send.vis.ee/#other-sample-url  17h38m\n3  https://example.com/#sample-share-url       37m30s\n\n# Change the password after uploading\n$ ffsend password https://send.vis.ee/#sample-share-url\nPassword: ******\n\n# Delete a file\n$ ffsend delete https://send.vis.ee/#sample-share-url\n```\n\nUse the `--help` flag, `help` subcommand, or see the [help](#help) section for\nall available subcommands.\n\n## Requirements\n- Linux, macOS, Windows, FreeBSD, Android (other BSDs might work)\n- A terminal :sunglasses:\n- Internet connection\n- Linux:\n  - OpenSSL & CA certificates:\n    - Ubuntu, Debian and derivatives: `apt install openssl ca-certificates`\n  - Optional: `xclip` or `xsel` for clipboard support\n    - Ubuntu, Debian and derivatives: `apt install xclip`\n    - CentOS/Red Hat/openSUSE/Fedora: `yum install xclip`\n    - Arch: `pacman -S xclip`\n- Windows specific:\n  - Optional OpenSSL with `crypto-openssl` feature: [» Installer][openssl-windows-installer] (`v1.1.0j` or above)\n- macOS specific:\n  - Optional OpenSSL with `crypto-openssl` feature: `brew install openssl@1.1`\n- FreeBSD specific:\n  - OpenSSL: `pkg install openssl`\n  - CA certificates: `pkg install ca_root_nss`\n  - Optional `xclip` & `xsel` for clipboard support: `pkg install xclip xsel-conrad`\n- Android specific:\n  - Termux: [» Termux][termux]\n\n## Install\nBecause `ffsend` is still in early stages, only limited installation options are\navailable right now. Feel free to contribute additional packages.\n\nMake sure you meet and install the [requirements](#requirements).\n\nSee the operating system specific instructions below:\n- [Linux](#linux-all-distributions)\n- [macOS](#macos)\n- [Windows](#windows)\n- [FreeBSD](#freebsd)\n- [Android](#android)\n- [_Other OS or architecture_](#other-os-or-architecture)\n\n### Linux (all distributions)\nUsing the [snap](#linux-snap-package) package is recommended if supported.  \nAlternatively you may install it manually using the\n[prebuilt binaries](#linux-prebuilt-binaries).\n\nOnly 64-bit (`x86_64`) packages and binaries are provided.\nFor other architectures and configurations you may [compile from source](#build).\n\nMore packages options will be coming soon.\n\n#### Linux: snap package\n_Note: The `ffsend` `snap` package is isolated, and can only access files in\nyour home directory. Choose a different installation option if you don't want\nthis limitation._\n\n_Note: due to how `snap` is configured by default, you won't be able to use the\npackage from some contexts such as through SSH without manual modifications. If\nyou're experiencing problems, please refer to a different installation method\nsuch as the [prebuilt binaries](#linux-prebuilt-binaries), or open an issue._\n_Note: if you want to read/write to a flash drive run `snap connect ffsend:removable-media`\n\n[» `ffsend`][snapcraft-ffsend]\n\n```bash\nsnap install ffsend\nffsend --help\n```\n\n#### Linux: Arch AUR packages\n[» `ffsend-bin`][aur-ffsend-bin] (precompiled binary, latest release, recommended)  \n[» `ffsend`][aur-ffsend] (compiles from source, latest release)  \n[» `ffsend-git`][aur-ffsend-git] (compiles from source, latest `master` commit)\n\n```bash\nyay -S ffsend\n# or\naurto add ffsend-bin\nsudo pacman -S ffsend-bin\n# or using any other AUR helper\n\nffsend --help\n```\n\n#### Linux: Nix package\n_Note: The Nix package is currently not automatically updated, and might be\nslightly outdated._\n\n[» ffsend][nix-ffsend]\n\n```bash\nnix-channel --update\nnix-env --install ffsend\n\nffsend --help\n```\n\n#### Linux: Fedora package\n_Note: The Fedora package is maintained by contributors, and might be\nslightly outdated._\n\n[» ffsend][fedora-ffsend]\n\n```bash\nsudo dnf install ffsend\n\nffsend --help\n```\n\n#### Linux: Alpine package\n_Note: The Alpine package is maintained by contributors, it might be outdated.\nChoose a different installation method if an important update is missing._\n\n[» ffsend][alpine-ffsend]\n\n```bash\napk add ffsend --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing\n\nffsend --help\n```\n\n#### Linux: Prebuilt binaries\nCheck out the [latest release][github-latest-release] assets for Linux binaries.  \nUse the `ffsend-v*-linux-x64-static` binary, to minimize the chance for issues.\nIf it isn't available yet, you may use an artifact from a\n[previous version][github-releases] instead, until it is available.\n\nMake sure you meet and install the [requirements](#requirements) before you\ncontinue.\n\nYou must make the binary executable, and may want to move it into `/usr/bin` to\nmake it easily executable:\n\n```bash\n# Rename binary to ffsend\nmv ./ffsend-* ./ffsend\n\n# Mark binary as executable\nchmod a+x ./ffsend\n\n# Move binary into path, to make it easily usable\nsudo mv ./ffsend /usr/local/bin/\n\nffsend --help\n```\n\n### macOS\nUsing the [`homebrew` package](#macos-homebrew-package) is recommended.  \nAlternatively you may install it via [MacPorts](#macos-macports), or manually using the\n[prebuilt binaries](#macos-prebuilt-binaries).\n\n#### macOS: homebrew package\nMake sure you've [`homebrew`][homebrew] installed, and run:\n\n```bash\nbrew install ffsend\nffsend --help\n```\n\n#### macOS: MacPorts\n_Note: ffsend in MacPorts is currently not automatically updated, and might be\nslightly outdated._\n\nOnce you have [MacPorts](https://www.macports.org) installed, you can run:\n\n```bash\nsudo port selfupdate\nsudo port install ffsend\n```\n\n#### macOS: Nix package\n_Note: The Nix package is currently not automatically updated, and might be\nslightly outdated._\n\n```bash\nnix-channel --update\nnix-env --install ffsend\n\nffsend --help\n```\n\n#### macOS: Prebuilt binaries\nCheck out the [latest release][github-latest-release] assets for a macOS binary.\nIf it isn't available yet, you may use an artifact from a\n[previous version][github-releases] instead, until it is available.\n\nThen, mark the downloaded binary as an executable.\nYou then may want to move it into `/usr/local/bin/` to make the `ffsend` command\nglobally available:\n\n```bash\n# Rename file to ffsend\nmv ./ffsend-* ./ffsend\n\n# Mark binary as executable\nchmod a+x ./ffsend\n\n# Move binary into path, to make it easily usable\nsudo mv ./ffsend /usr/local/bin/\n\nffsend\n```\n\n### Windows\nUsing the [`scoop` package](#windows-scoop-package) is recommended.  \nAlternatively you may install it manually using the\n[prebuilt binaries](#windows-prebuilt-binaries).\n\nIf you're using the [Windows Subsystem for Linux][wsl], it's highly recommended\nto install the [prebuilt Linux binary](#prebuilt-binaries-for-linux) instead.\n\nOnly 64-bit (`x86_64`) binaries are provided.\nFor other architectures and configurations you may [compile from source](#build).\n\nA `chocolatey` package along with an `.msi` installer will be coming soon.\n\n#### Windows: scoop package\nMake sure you've [`scoop`][scoop-install] installed, and run:\n\n```bash\nscoop install ffsend\nffsend --help\n```\n\n#### Windows: Prebuilt binaries\nCheck out the [latest release][github-latest-release] assets for Windows binaries.\nUse the `ffsend-v*-windows-x64-static` binary, to minimize the chance for issues.\nIf it isn't available yet, you may use an artifact from a\n[previous version][github-releases] instead, until it is available.\n\nYou can use `ffsend` from the command line in the same directory:\n```cmd\n.\\ffsend.exe --help\n```\n\nTo make it globally invocable as `ffsend`, you must make the binary available in\nyour systems `PATH`. The easiest solution is to move it into `System32`:\n```cmd\nmove .\\ffsend.exe C:\\Windows\\System32\\ffsend.exe\n```\n\n### FreeBSD\n\n[» `ffsend`][freshports-ffsend]\n\n_Note: The FreeBSD package is currently maintained by FreeBSD contributors,\nand might be slightly outdated._\n\n```sh\n# Precompiled binary.\npkg install ffsend\n\n# Compiles and installs from source.\ncd /usr/ports/www/ffsend && make install\n```\n\n### Android\n`ffsend` can be used on Android through Termux, install it first:\n[» Termux][termux]\n\n_Note: The Android package is currently maintained by Termux contributors,\nand might be slightly outdated._\n\n```sh\n# Install package.\npkg install ffsend\n\nffsend help\n```\n\n### Other OS or architecture\nIf your system runs Docker, you can use the [docker image](#docker-image).\nThere are currently no other binaries or packages available.\n\nYou can [build the project from source](#build) instead.\n\n#### Docker image\nA Docker image is available for using `ffsend` running in a container.\nMount a directory to `/data`, so it's accessible for `ffsend` in the container,\nand use the command as you normally would.\n\n[» `timvisee/ffsend`][docker-hub-ffsend]\n\n```bash\n# Invoke without arguments\ndocker run --rm -it -v $(pwd):/data timvisee/ffsend\n\n# Upload my-file.txt\ndocker run --rm -it -v $(pwd):/data timvisee/ffsend upload my-file.txt\n\n# Download from specified link\ndocker run --rm -it -v $(pwd):/data timvisee/ffsend download https://send.vis.ee/#sample-share-url\n\n# Show help\ndocker run --rm -it -v $(pwd):/data timvisee/ffsend help\n\n# To update the used image\ndocker pull timvisee/ffsend\n```\n\nOn Linux or macOS you might define a alias in your shell configuration, to make\nit invocable as `ffsend`:\n\n```bash\nalias ffsend='docker run --rm -it -v \"$(pwd):/data\" timvisee/ffsend'\n```\n\n_Note: This implementation is limited to accessing the paths you make available\nthrough the specified mount._\n\n## Build\nTo build and install `ffsend` yourself, you meet the following requirements\nbefore proceeding:\n\n### Build requirements\n- Runtime [requirements](#requirements)\n- [`git`][git]\n- [`rust`][rust] `v1.63` (MSRV) or higher (install using [`rustup`][rustup])\n- [OpenSSL][openssl] or [LibreSSL][libressl] libraries/headers:\n  - Linux:\n    - Ubuntu, Debian and derivatives: `apt install build-essential cmake pkg-config libssl-dev`\n    - CentOS/Red Hat/openSUSE: `yum install gcc gcc-c++ make cmake openssl-devel`\n    - Arch: `pacman -S openssl base-devel`\n    - Gentoo: `emerge -a dev-util/pkgconfig dev-util/cmake dev-libs/openssl`\n    - Fedora: `dnf install gcc gcc-c++ make cmake openssl-devel`\n    - Or see instructions [here](https://github.com/sfackler/rust-openssl#linux)\n  - Windows:\n    - Optional with `crypto-openssl` feature: See instructions here [here](https://github.com/sfackler/rust-openssl#windows-msvc)\n  - macOS:\n    - Optional with `crypto-openssl` feature: `brew install cmake pkg-config openssl` or see instructions [here](https://github.com/sfackler/rust-openssl#osx)\n  - FreeBSD:\n    - `pkg install rust gmake pkgconf python36 libxcb xclip ca_root_nss xsel-conrad`\n    - It is a better idea to use & modify the existing `ffsend` port, which manages dependencies for you.\n\n### Compile and install\nThen, walk through one of the following steps to compile and install `ffsend`:\n\n- Compile and install it directly from cargo:\n\n  ```bash\n  # Compile and install from cargo\n  cargo install ffsend -f\n\n  # Start using ffsend\n  ffsend --help\n  ```\n\n- Or clone the repository and install it with `cargo`:\n\n  ```bash\n  # Clone the project\n  git clone https://github.com/timvisee/ffsend.git\n  cd ffsend\n\n  # Compile and install\n  cargo install --path . -f\n\n  # Start using ffsend\n  ffsend --help\n\n  # or run it directly from cargo\n  cargo run --release -- --help\n  ```\n\n- Or clone the repository and invoke the binary directly (Linux/macOS):\n\n  ```bash\n  # Clone the project\n  git clone https://github.com/timvisee/ffsend.git\n  cd ffsend\n\n  # Build the project (release version)\n  cargo build --release\n\n  # Start using ffsend\n  ./target/release/ffsend --help\n  ```\n\n### Compile features / use flags\nDifferent use flags are available for `ffsend` to toggle whether to include\nvarious features.\nThe following features are available, some of which are enabled by default:\n\n| Feature         | Enabled | Description                                                |\n| :-------------: | :-----: | :--------------------------------------------------------- |\n| `send2`         | Default | Support for Send v2 servers                                |\n| `send3`         | Default | Support for Send v3 servers                                |\n| `crypto-ring`   | Default | Use ring as cryptography backend                           |\n| `crypto-openssl`|         | Use OpenSSL as cryptography backend                        |\n| `clipboard`     | Default | Support for copying links to the clipboard                 |\n| `history`       | Default | Support for tracking files in history                      |\n| `archive`       | Default | Support for archiving and extracting uploads and downloads |\n| `qrcode`        | Default | Support for rendering a QR code for a share URL            |\n| `urlshorten`    | Default | Support for shortening share URLs                          |\n| `infer-command` | Default | Support for inferring subcommand based on binary name      |\n| `no-color`      |         | Compile without color support in error and help messages   |\n\nTo enable features during building or installation, specify them with\n`--features <features...>` when using `cargo`.\nYou may want to disable default features first using\n`--no-default-features`.\nHere are some examples:\n\n```bash\n# Defaults set of features with no-color, one of\ncargo install --features no-color\ncargo build --release --features no-color\n\n# No default features, except required\ncargo install --no-default-features --features send3,crypto-ring\n\n# With history and clipboard support\ncargo install --no-default--features --features send3,crypto-ring,history,clipboard\n```\n\nFor Windows systems it is recommended to provide the `no-color` flag, as color\nsupport in Windows terminals is flaky.\n\n## Configuration and environment\nThe following environment variables may be used to configure the following\ndefaults. The CLI flag is shown along with it, to better describe the relation\nto command line arguments:\n\n| Variable                  | CLI flag                       | Description                                   |\n| :------------------------ | :----------------------------: | :-------------------------------------------- |\n| `FFSEND_HISTORY`          | `--history <FILE>`             | History file path                             |\n| `FFSEND_HOST`             | `--host <URL>`                 | Upload host                                   |\n| `FFSEND_TIMEOUT`          | `--timeout <SECONDS>`          | Request timeout (0 to disable)                |\n| `FFSEND_TRANSFER_TIMEOUT` | `--transfer-timeout <SECONDS>` | Transfer timeout (0 to disable)               |\n| `FFSEND_EXPIRY_TIME`      | `--expiry-time <SECONDS>`      | Default upload expiry time                    |\n| `FFSEND_DOWNLOAD_LIMIT`   | `--download-limit <DOWNLOADS>` | Default download limit                        |\n| `FFSEND_API`              | `--api <VERSION>`              | Server API version, `-` to lookup             |\n| `FFSEND_BASIC_AUTH`       | `--basic-auth <USER:PASSWORD>` | Basic HTTP authentication credentials to use. |\n\nThese environment variables may be used to toggle a flag, simply by making them\navailable. The actual value of these variables is ignored, and variables may be\nempty.\n\n| Variable             | CLI flag        | Description                        |\n| :------------------- | :-------------: | :--------------------------------- |\n| `FFSEND_FORCE`       | `--force`       | Force operations                   |\n| `FFSEND_NO_INTERACT` | `--no-interact` | No interaction for prompts         |\n| `FFSEND_YES`         | `--yes`         | Assume yes for prompts             |\n| `FFSEND_INCOGNITO`   | `--incognito`   | Incognito mode, don't use history  |\n| `FFSEND_OPEN`        | `--open`        | Open share link of uploaded file   |\n| `FFSEND_ARCHIVE`     | `--archive`     | Archive files uploaded             |\n| `FFSEND_EXTRACT`     | `--extract`     | Extract files downloaded           |\n| `FFSEND_COPY`        | `--copy`        | Copy share link to clipboard       |\n| `FFSEND_COPY_CMD`    | `--copy-cmd`    | Copy download command to clipboard |\n| `FFSEND_QUIET`       | `--quiet`       | Log quiet information              |\n| `FFSEND_VERBOSE`     | `--verbose`     | Log verbose information            |\n\nSome environment variables may be set at compile time to tweak some defaults.\n\n| Variable     | Description                                                                |\n| :----------- | :------------------------------------------------------------------------- |\n| `XCLIP_PATH` | Set fixed `xclip` binary path when using `clipboard-bin` (Linux, &ast;BSD) |\n| `XSEL_PATH`  | Set fixed `xsel` binary path when using `clipboard-bin` (Linux, &ast;BSD)  |\n\nAt this time, no configuration or _dotfile_ file support is available.\nThis will be something added in a later release.\n\n### Binary for each subcommand: `ffput`, `ffget`\n`ffsend` supports having a separate binaries for single subcommands, such as\nhaving `ffput` and `ffget` just for to upload and download using `ffsend`.\nThis allows simple and direct commands like:\n```bash\nffput my-file.txt\nffget https://send.vis.ee/#sample-share-url\n```\n\nThis works for a predefined list of binary names:\n\n- `ffput` → `ffsend upload ...`\n- `ffget` → `ffsend download ...`\n- `ffdel` → `ffsend delete ...`\n- _This list is defined in [`src/config.rs`](./src/config.rs) as `INFER_COMMANDS`_\n\nYou can use the following methods to set up these single-command binaries:\n\n- Create a properly named symbolic link (recommended)\n- Create a properly named hard link\n- Clone the `ffsend` binary, and rename it\n\nOn Linux and macOS you can use the following command to set up symbolic links in\nthe current directory:\n\n```bash\nln -s $(which ffsend) ./ffput\nln -s $(which ffsend) ./ffget\n```\n\nSupport for this feature is only available when `ffsend` is compiled with the\n[`infer-command`](#compile-features--use-flags) feature flag.\nThis is usually enabled by default.\nTo verify support is available with an existing installation, make sure the\nfeature is listed when invoking `ffsend debug`.\n\nNote that the `snap` package does currently not support this due to how this\npackage format works.\n\n### Scriptability\n`ffsend` is optimized for use in automated scripts. It provides some specialized\narguments to control `ffsend` without user interaction.\n\n- `--no-interact` (`-I`): do not allow user interaction. For prompts not having\n    a default value, the application will quit with an error, unless `--yes`\n    or `--force` is provided.\n    This should **always** be given when using automated scripting.  \n    Example: when uploading a directory, providing this flag will stop the\n    archive question prompt form popping up, and will archive the directory as\n    default option.\n- `--yes` (`-y`): assume the yes option for yes/no prompt by default.  \n    Example: when downloading a file that already exists, providing this flag\n    will assume yes when asking to overwrite a file.\n- `--force` (`-f`): force to continue with the action, skips any warnings that\n    would otherwise quit the application.  \n    Example: when uploading a file that is too big, providing this flag will\n    ignore the file size warning and forcefully continues.\n- `--quiet` (`-q`): be quiet, print as little information as possible.  \n    Example: when uploading a file, providing this flag will only output the\n    final share URL.\n\nGenerally speaking, use the following rules when automating:\n- Always provide `--no-interact` (`-I`).\n- Provide any combination of `--yes` (`-y`) and `--force` (`-f`) for actions you\n  want to complete no matter what.\n- When passing share URLs along, provide the `--quiet` (`-q`) flag, when\n  uploading for example.\n\nThese flags can also automatically be set by defining environment variables as\nspecified here:  \n[» Configuration and environment](#configuration-and-environment)\n\nHere are some examples commands in `bash`:\n\n```bash\n# Stop on error\nset -e\n\n# Upload a file\n# -I: no interaction\n# -y: assume yes\n# -q: quiet output, just return the share link\nURL=$(ffsend -Iy upload -q my-file.txt)\n\n# Render file information\n# -I: no interaction\n# -f: force, just show the info\nffsend -If info $URL\n\n# Set a password for the uploaded file\nffsend -I password $URL --password=\"secret\"\n\n# Use the following flags automatically from now on\n# -I: no interaction\n# -f: force\n# -y: yes\nexport FFSEND_NO_INTERACT=1 FFSEND_FORCE=1 FFSEND_YES=1\n\n# Download the uploaded file, overwriting the local variant due to variables\nffsend download $URL --password=\"secret\"\n```\n\nFor more information on these arguments, invoke `ffsend help` and check out:\n[» Configuration and environment](#configuration-and-environment)\n\nFor other questions regarding automation or feature requests, be sure to\n[open](https://github.com/timvisee/ffsend/issues/) an issue.\n\n## Security\nIn short; the `ffsend` tool and the [Send][send] service can be considered\nsecure, and may be used to share sensitive files. Note though that the\ncreated share link for an upload will allow anyone to download the file.\nMake sure you don't share this link with unauthorized people.\n\nFor more detailed information on encryption, please read the rest of the\nparagraphs in this security section.\n\n_Note: even though the encryption method is considered secure, this `ffsend`\ntool does not provide any warranty in any way, shape or form for files that\nsomehow got decrypted without proper authorization._\n\n#### Client side encryption\n`ffsend` uses client side encryption, to ensure your files are securely\nencrypted before they are uploaded to the remote host. This makes it impossible\nfor third parties to decrypt your file without having the secret (encryption\nkey). The file and its metadata are encrypted using `128-bit AES-GCM`, and a\n`HMAC SHA-256` signing key is used for request authentication.\nThis is consistent with the encryption documentation provided by the\n[Send][send] service, `ffsend` is a tool for.\n\nA detailed list on the encryption/decryption steps, and on what encryption is\nexactly used can be found [here][send-encryption] in the official service\ndocumentation.\n\n#### Note on share link security\nThe encryption secret, that is used to decrypt the file when downloading,\nis included in the share URL behind the `#` (hash). This secret is never sent\nthe remote server directly when using the share link in your browser.\nIt would be possible however for a webpage to load some malicious JavaScript\nsnippet that eventually steals the secret from the link once the page is loaded.\nAlthough this scenario is extremely unlikely, there are some options to prevent\nthis from happening:\n\n- Only use this `ffsend` tool, do not use the share link in your browser.\n- Add additional protection by specifying a password using `--password` while\n  uploading, or using the `password` subcommand afterwards.\n- Host a secure [Send][send] service instance yourself.\n\nA complete overview on encryption can be found in the official service\ndocumentation [here][send-encryption].\n\n## Help\n```\n$ ffsend help\n\nffsend 0.2.72\nTim Visee <3a4fb3964f@sinenomine.email>\nEasily and securely share files from the command line.\nA fully featured Send client.\n\nThe default public Send host is provided by Tim Visee, @timvisee.\nPlease consider to donate and help keep it running: https://vis.ee/donate\n\nUSAGE:\n    ffsend [FLAGS] [OPTIONS] [SUBCOMMAND]\n\nFLAGS:\n    -f, --force          Force the action, ignore warnings\n    -h, --help           Prints help information\n    -i, --incognito      Don't update local history for actions\n    -I, --no-interact    Not interactive, do not prompt\n    -q, --quiet          Produce output suitable for logging and automation\n    -V, --version        Prints version information\n    -v, --verbose        Enable verbose information and logging\n    -y, --yes            Assume yes for prompts\n\nOPTIONS:\n    -A, --api <VERSION>                 Server API version to use, '-' to lookup [env: FFSEND_API]\n        --basic-auth <USER:PASSWORD>    Protected proxy HTTP basic authentication credentials (not FxA) [env: FFSEND_BASIC_AUTH]\n    -H, --history <FILE>                Use the specified history file [env: FFSEND_HISTORY]\n    -t, --timeout <SECONDS>             Request timeout (0 to disable) [env: FFSEND_TIMEOUT]\n    -T, --transfer-timeout <SECONDS>    Transfer timeout (0 to disable) [env: FFSEND_TRANSFER_TIMEOUT]\n\nSUBCOMMANDS:\n    upload        Upload files [aliases: u, up]\n    download      Download files [aliases: d, down]\n    debug         View debug information [aliases: dbg]\n    delete        Delete a shared file [aliases: del, rm]\n    exists        Check whether a remote file exists [aliases: e]\n    generate      Generate assets [aliases: gen]\n    help          Prints this message or the help of the given subcommand(s)\n    history       View file history [aliases: h]\n    info          Fetch info about a shared file [aliases: i]\n    parameters    Change parameters of a shared file [aliases: params]\n    password      Change the password of a shared file [aliases: pass, p]\n    version       Determine the Send server version [aliases: v]\n\nThis application is not affiliated with Firefox or Mozilla.\n```\n\n## Special thanks\n- to all `ffsend` source/package contributors\n- to [Mozilla][mozilla] for building the amazing [Firefox Send][mozilla-send] service ([fork][timvisee-send])\n- to everyone involved with [asciinema][asciinema] and [svg-term][svg-term] for\n  providing tools to make great visual demos\n- to everyone involved in all crate dependencies used\n\n## License\nThis project is released under the GNU GPL-3.0 license.\nCheck out the [LICENSE](LICENSE) file for more information.\n\n[usage-demo-asciinema]: https://asciinema.org/a/182225\n[usage-demo-svg]: https://cdn.rawgit.com/timvisee/ffsend/6e8ef55b/res/demo.svg\n[firefox]: https://firefox.com/\n[git]: https://git-scm.com/\n[libressl]: https://libressl.org/\n[mozilla]: https://mozilla.org/\n[openssl]: https://www.openssl.org/\n[openssl-windows-installer]: https://u.visee.me/dl/openssl/Win64OpenSSL_Light-1_1_0j.exe\n[termux]: https://termux.com/\n[rust]: https://rust-lang.org/\n[rustup]: https://rustup.rs/\n[send]: https://github.com/timvisee/send\n[mozilla-send]: https://github.com/mozilla/send\n[timvisee-send]: https://github.com/timvisee/send\n[send-encryption]: https://github.com/timvisee/send/blob/master/docs/encryption.md\n[asciinema]: https://asciinema.org/\n[svg-term]: https://github.com/marionebl/svg-term-cli\n[github-releases]: https://github.com/timvisee/ffsend/releases\n[github-latest-release]: https://github.com/timvisee/ffsend/releases/latest\n[nix-ffsend]: https://nixos.org/nixos/packages.html?attr=ffsend&channel=nixos-unstable&query=ffsend\n[fedora-ffsend]: https://src.fedoraproject.org/rpms/rust-ffsend\n[aur-ffsend]: https://aur.archlinux.org/packages/ffsend/\n[aur-ffsend-bin]: https://aur.archlinux.org/packages/ffsend-bin/\n[aur-ffsend-git]: https://aur.archlinux.org/packages/ffsend-git/\n[alpine-ffsend]: https://pkgs.alpinelinux.org/packages?name=ffsend&branch=edge\n[snapcraft-ffsend]: https://snapcraft.io/ffsend\n[homebrew]: https://brew.sh/\n[wsl]: https://docs.microsoft.com/en-us/windows/wsl/install-win10\n[docker-hub-ffsend]: https://hub.docker.com/r/timvisee/ffsend\n[scoop-install]: https://scoop.sh/#installs-in-seconds\n[freshports-ffsend]: https://www.freshports.org/www/ffsend\n[timvisee]: https://timvisee.com/\n[donate]: https://timvisee.com/donate\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported          |\n| ------- | ------------------ |\n| 0.2.x   | :white_check_mark: |\n\n## Reporting a Vulnerability\n\nTo report a vulnerability in this project, or in one if it's dependency;\nplease [open](https://gitlab.com/timvisee/ffsend/issues/new) a new issue\non GitLab (or on [GitHub](https://github.com/timvisee/ffsend/issues/new)) describing the situation.\n\nFor confidential issues, you may send an email to the main developer (@timvisee) at: `3a4fb3964f@sinenomine.email`  \nOr see other methods of contacting over on: [timvisee.com/contact](https://timvisee.com/contact)\n\nTo contribute code for fixing a vulnerability, please refer to the [contribution](./CONTRIBUTING.md) document.\n"
  },
  {
    "path": "appveyor.yml",
    "content": "# AppVeyor CI configuration for building Windows binaries for ffsend.\n# These Windows binaries are published on GitHub as release files.\n#\n# The main CI runs on GitLab CI at: https://gitlab.com/timvisee/ffsend/pipelines\n\n# Only build version tags\nskip_non_tags: true\nbranches:\n  only:\n    - /v\\d*\\.\\d*\\.\\d*/\n\n# Build for the x86_64 Windows target\nplatform: x64\nenvironment:\n  RUSTUP_USE_HYPER: 1\n  CARGO_HTTP_CHECK_REVOKE: false\n  GITHUB_TOKEN:\n    secure: jqZ4q5oOthKX/pBL1tRsBJsfGPIee3q+N/UBSCZNjCrlFUNfQSfibBPzzICYg1he\n  CHOCOLATEY_TOKEN:\n    secure: k5Q57xoXa6qSFScSpRaww2puW0yjYoH19uIq3qS1emOG+lNs9TYCnWYhUzQ2gzfc\n\n  matrix:\n    - TARGET: x86_64-pc-windows-msvc\n      BITS: 64\n\n# Extract release binary artifacts\nartifacts:\n- path: .\\ffsend*.exe\n- path: .\\ffsend.*.nupkg\n\n# Install dependencies: Rust\ninstall:\n  # Install Rust\n  - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe\n  - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain stable\n  - set PATH=%PATH%;C:\\Users\\appveyor\\.cargo\\bin\n  - rustc -V\n  - cargo -V\n  - git submodule update --init\n\n# Build dynamic and static Windows binaries, release on GitHub\nbuild_script:\n  # Build dynamic release binary\n  - cargo build --release --features no-color --verbose\n  - copy .\\target\\release\\ffsend.exe .\\ffsend-%TARGET%.exe\n\n  # Build static release binary\n  - set RUSTFLAGS=-Ctarget-feature=+crt-static\n  - cargo build --release --features no-color --verbose\n  - copy .\\target\\release\\ffsend.exe .\\ffsend-%TARGET%-static.exe\n\n  # Install github-release\n  - appveyor DownloadFile https://github.com/tfausak/github-release/releases/download/1.2.4/github-release-windows.zip -FileName github-release.zip\n  - 7z e github-release.zip\n\n  # Collect binary, set package version and build chocolatey package\n  - copy .\\ffsend-%TARGET%-static.exe .\\pkg\\choco\\ffsend\\tools\\ffsend.exe\n  - cd .\\pkg\\choco\\ffsend\\\n  - ps: echo $env:APPVEYOR_REPO_TAG_NAME\n  - ps: ((Get-Content -path .\\ffsend.nuspec -Raw) -replace \"0.0.0\",$env:APPVEYOR_REPO_TAG_NAME.Substring(1)) | Set-Content -Path .\\ffsend.nuspec\n  - choco pack\n  - copy ffsend.*.nupkg ..\\..\\..\\\n  - cd ..\\..\\..\\\n\n  # Create the release, upload the binaries\n  # TODO: fix the line below, which is causing CI to error\n  # - ps: Invoke-Expression -Command '$ErrorActionPreference = \"SilentlyContinue\"; .\\github-release.exe release --token $env:GITHUB_TOKEN --owner timvisee --repo ffsend --tag $env:APPVEYOR_REPO_TAG_NAME --title \"ffsend $env:APPVEYOR_REPO_TAG_NAME\"; exit 0'\n  - ps: .\\github-release.exe upload --token $env:GITHUB_TOKEN --owner timvisee --repo ffsend --tag $env:APPVEYOR_REPO_TAG_NAME --file .\\ffsend-$env:TARGET.exe --name ffsend-$env:APPVEYOR_REPO_TAG_NAME-windows-x64.exe\n  - ps: .\\github-release.exe upload --token $env:GITHUB_TOKEN --owner timvisee --repo ffsend --tag $env:APPVEYOR_REPO_TAG_NAME --file .\\ffsend-$env:TARGET-static.exe --name ffsend-$env:APPVEYOR_REPO_TAG_NAME-windows-x64-static.exe\n  - ps: .\\github-release.exe upload --token $env:GITHUB_TOKEN --owner timvisee --repo ffsend --tag $env:APPVEYOR_REPO_TAG_NAME --file (Get-Item .\\ffsend.*.nupkg).FullName --name ffsend-$env:APPVEYOR_REPO_TAG_NAME.nupkg\n\n  # Publish the chocolatey package\n  # TODO: re-enable when chocolatey is properly accepting packages again\n  # - cd .\\pkg\\choco\\ffsend\\\n  # - choco push --api-key %CHOCOLATEY_TOKEN%\n  # - cd ..\\..\\..\\\n\n# We don't test anything here\ntest: false\n"
  },
  {
    "path": "build.rs",
    "content": "fn main() {\n    #[cfg(all(\n        feature = \"clipboard\",\n        any(\n            target_os = \"linux\",\n            target_os = \"freebsd\",\n            target_os = \"dragonfly\",\n            target_os = \"openbsd\",\n            target_os = \"netbsd\",\n        )\n    ))]\n    {\n        // Select clipboard binary method\n        #[cfg(not(feature = \"clipboard-crate\"))]\n        println!(\"cargo:rustc-cfg=feature=\\\"clipboard-bin\\\"\");\n\n        // xclip and xsel paths are inserted at compile time\n        println!(\"cargo:rerun-if-env-changed=XCLIP_PATH\");\n        println!(\"cargo:rerun-if-env-changed=XSEL_PATH\");\n    }\n\n    #[cfg(all(\n        feature = \"clipboard\",\n        not(any(\n            target_os = \"linux\",\n            target_os = \"freebsd\",\n            target_os = \"dragonfly\",\n            target_os = \"openbsd\",\n            target_os = \"netbsd\",\n        ))\n    ))]\n    {\n        // Select clipboard crate method\n        #[cfg(not(feature = \"clipboard-bin\"))]\n        println!(\"cargo:rustc-cfg=feature=\\\"clipboard-crate\\\"\");\n    }\n}\n"
  },
  {
    "path": "contrib/completions/_ffsend",
    "content": "#compdef ffsend\n\nautoload -U is-at-least\n\n_ffsend() {\n    typeset -A opt_args\n    typeset -a _arguments_options\n    local ret=1\n\n    if is-at-least 5.2; then\n        _arguments_options=(-s -S -C)\n    else\n        _arguments_options=(-s -C)\n    fi\n\n    local context curcontext=\"$curcontext\" state line\n    _arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n\":: :_ffsend_commands\" \\\n\"*::: :->ffsend\" \\\n&& ret=0\n    case $state in\n    (ffsend)\n        words=($line[1] \"${words[@]}\")\n        (( CURRENT += 1 ))\n        curcontext=\"${curcontext%:*:*}:ffsend-command-$line[1]:\"\n        case $line[1] in\n            (dbg)\n_arguments \"${_arguments_options[@]}\" \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(debug)\n_arguments \"${_arguments_options[@]}\" \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(del)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(rm)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(delete)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(d)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-o+[Output file or directory]' \\\n'--output=[Output file or directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-e[Extract an archived file]' \\\n'--extract[Extract an archived file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(down)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-o+[Output file or directory]' \\\n'--output=[Output file or directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-e[Extract an archived file]' \\\n'--extract[Extract an archived file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(download)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-o+[Output file or directory]' \\\n'--output=[Output file or directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-e[Extract an archived file]' \\\n'--extract[Extract an archived file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(e)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(exist)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(exists)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(gen)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n\":: :_ffsend__generate_commands\" \\\n\"*::: :->generate\" \\\n&& ret=0\ncase $state in\n    (generate)\n        words=($line[1] \"${words[@]}\")\n        (( CURRENT += 1 ))\n        curcontext=\"${curcontext%:*:*}:ffsend-generate-command-$line[1]:\"\n        case $line[1] in\n            (completion)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(complete)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(completions)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(help)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n        esac\n    ;;\nesac\n;;\n(generate)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n\":: :_ffsend__generate_commands\" \\\n\"*::: :->generate\" \\\n&& ret=0\ncase $state in\n    (generate)\n        words=($line[1] \"${words[@]}\")\n        (( CURRENT += 1 ))\n        curcontext=\"${curcontext%:*:*}:ffsend-generate-command-$line[1]:\"\n        case $line[1] in\n            (completion)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(complete)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(completions)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Shell completion files output directory]' \\\n'--output=[Shell completion files output directory]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':SHELL -- Shell type to generate completions for:(all zsh bash fish powershell elvish)' \\\n&& ret=0\n;;\n(help)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n        esac\n    ;;\nesac\n;;\n(i)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(information)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(info)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-p+[Unlock a password protected file]' \\\n'--password=[Unlock a password protected file]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(params)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(param)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(parameter)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(parameters)\n_arguments \"${_arguments_options[@]}\" \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(pass)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Specify a password, do not prompt]' \\\n'--password=[Specify a password, do not prompt]' \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(p)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Specify a password, do not prompt]' \\\n'--password=[Specify a password, do not prompt]' \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(password)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Specify a password, do not prompt]' \\\n'--password=[Specify a password, do not prompt]' \\\n'-o+[Specify the file owner token]' \\\n'--owner=[Specify the file owner token]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':URL -- The share URL:_files' \\\n&& ret=0\n;;\n(u)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Protect the file with a password]' \\\n'--password=[Protect the file with a password]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-e+[The file expiry time]' \\\n'--expiry-time=[The file expiry time]' \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-n+[Rename the file being uploaded]' \\\n'--name=[Rename the file being uploaded]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-o[Open the share link in your browser]' \\\n'--open[Open the share link in your browser]' \\\n'-D[Delete local file after upload]' \\\n'--delete[Delete local file after upload]' \\\n'-a[Archive the upload in a single file]' \\\n'--archive[Archive the upload in a single file]' \\\n'(-C --copy-cmd)-c[Copy the share link to your clipboard]' \\\n'(-C --copy-cmd)--copy[Copy the share link to your clipboard]' \\\n'(-c --copy)-C[Copy the ffsend download command to your clipboard]' \\\n'(-c --copy)--copy-cmd[Copy the ffsend download command to your clipboard]' \\\n'-S[Shorten share URLs with a public service]' \\\n'--shorten[Shorten share URLs with a public service]' \\\n'-Q[Print a QR code for the share URL]' \\\n'--qrcode[Print a QR code for the share URL]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':FILE -- The file(s) to upload:_files' \\\n&& ret=0\n;;\n(up)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Protect the file with a password]' \\\n'--password=[Protect the file with a password]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-e+[The file expiry time]' \\\n'--expiry-time=[The file expiry time]' \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-n+[Rename the file being uploaded]' \\\n'--name=[Rename the file being uploaded]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-o[Open the share link in your browser]' \\\n'--open[Open the share link in your browser]' \\\n'-D[Delete local file after upload]' \\\n'--delete[Delete local file after upload]' \\\n'-a[Archive the upload in a single file]' \\\n'--archive[Archive the upload in a single file]' \\\n'(-C --copy-cmd)-c[Copy the share link to your clipboard]' \\\n'(-C --copy-cmd)--copy[Copy the share link to your clipboard]' \\\n'(-c --copy)-C[Copy the ffsend download command to your clipboard]' \\\n'(-c --copy)--copy-cmd[Copy the ffsend download command to your clipboard]' \\\n'-S[Shorten share URLs with a public service]' \\\n'--shorten[Shorten share URLs with a public service]' \\\n'-Q[Print a QR code for the share URL]' \\\n'--qrcode[Print a QR code for the share URL]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':FILE -- The file(s) to upload:_files' \\\n&& ret=0\n;;\n(upload)\n_arguments \"${_arguments_options[@]}\" \\\n'-p+[Protect the file with a password]' \\\n'--password=[Protect the file with a password]' \\\n'-d+[The file download limit]' \\\n'--download-limit=[The file download limit]' \\\n'-e+[The file expiry time]' \\\n'--expiry-time=[The file expiry time]' \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-n+[Rename the file being uploaded]' \\\n'--name=[Rename the file being uploaded]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'(-p --password)-P[Protect the file with a generated passphrase]' \\\n'(-p --password)--gen-passphrase[Protect the file with a generated passphrase]' \\\n'-o[Open the share link in your browser]' \\\n'--open[Open the share link in your browser]' \\\n'-D[Delete local file after upload]' \\\n'--delete[Delete local file after upload]' \\\n'-a[Archive the upload in a single file]' \\\n'--archive[Archive the upload in a single file]' \\\n'(-C --copy-cmd)-c[Copy the share link to your clipboard]' \\\n'(-C --copy-cmd)--copy[Copy the share link to your clipboard]' \\\n'(-c --copy)-C[Copy the ffsend download command to your clipboard]' \\\n'(-c --copy)--copy-cmd[Copy the ffsend download command to your clipboard]' \\\n'-S[Shorten share URLs with a public service]' \\\n'--shorten[Shorten share URLs with a public service]' \\\n'-Q[Print a QR code for the share URL]' \\\n'--qrcode[Print a QR code for the share URL]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n':FILE -- The file(s) to upload:_files' \\\n&& ret=0\n;;\n(ver)\n_arguments \"${_arguments_options[@]}\" \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(v)\n_arguments \"${_arguments_options[@]}\" \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(version)\n_arguments \"${_arguments_options[@]}\" \\\n'-h+[The remote host to upload to]' \\\n'--host=[The remote host to upload to]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(h)\n_arguments \"${_arguments_options[@]}\" \\\n'-R+[Remove history entry]' \\\n'--rm=[Remove history entry]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-C[Clear all history]' \\\n'--clear[Clear all history]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(ls)\n_arguments \"${_arguments_options[@]}\" \\\n'-R+[Remove history entry]' \\\n'--rm=[Remove history entry]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-C[Clear all history]' \\\n'--clear[Clear all history]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(history)\n_arguments \"${_arguments_options[@]}\" \\\n'-R+[Remove history entry]' \\\n'--rm=[Remove history entry]' \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-C[Clear all history]' \\\n'--clear[Clear all history]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n(help)\n_arguments \"${_arguments_options[@]}\" \\\n'-t+[Request timeout (0 to disable)]' \\\n'--timeout=[Request timeout (0 to disable)]' \\\n'-T+[Transfer timeout (0 to disable)]' \\\n'--transfer-timeout=[Transfer timeout (0 to disable)]' \\\n'-A+[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--api=[Server API version to use, '\\''-'\\'' to lookup]' \\\n'--basic-auth=[Protected proxy HTTP basic authentication credentials (not FxA)]' \\\n'-H+[Use the specified history file]' \\\n'--history=[Use the specified history file]' \\\n'-h[Prints help information]' \\\n'--help[Prints help information]' \\\n'-V[Prints version information]' \\\n'--version[Prints version information]' \\\n'-f[Force the action, ignore warnings]' \\\n'--force[Force the action, ignore warnings]' \\\n'-I[Not interactive, do not prompt]' \\\n'--no-interact[Not interactive, do not prompt]' \\\n'-y[Assume yes for prompts]' \\\n'--yes[Assume yes for prompts]' \\\n'-q[Produce output suitable for logging and automation]' \\\n'--quiet[Produce output suitable for logging and automation]' \\\n'*-v[Enable verbose information and logging]' \\\n'*--verbose[Enable verbose information and logging]' \\\n'-i[Don'\\''t update local history for actions]' \\\n'--incognito[Don'\\''t update local history for actions]' \\\n&& ret=0\n;;\n        esac\n    ;;\nesac\n}\n\n(( $+functions[_ffsend_commands] )) ||\n_ffsend_commands() {\n    local commands; commands=(\n        \"debug:View debug information\" \\\n\"dbg:View debug information\" \\\n\"delete:Delete a shared file\" \\\n\"del:Delete a shared file\" \\\n\"rm:Delete a shared file\" \\\n\"download:Download files\" \\\n\"d:Download files\" \\\n\"down:Download files\" \\\n\"exists:Check whether a remote file exists\" \\\n\"e:Check whether a remote file exists\" \\\n\"generate:Generate assets\" \\\n\"gen:Generate assets\" \\\n\"info:Fetch info about a shared file\" \\\n\"i:Fetch info about a shared file\" \\\n\"parameters:Change parameters of a shared file\" \\\n\"params:Change parameters of a shared file\" \\\n\"password:Change the password of a shared file\" \\\n\"pass:Change the password of a shared file\" \\\n\"p:Change the password of a shared file\" \\\n\"upload:Upload files\" \\\n\"u:Upload files\" \\\n\"up:Upload files\" \\\n\"version:Determine the Send server version\" \\\n\"v:Determine the Send server version\" \\\n\"history:View file history\" \\\n\"h:View file history\" \\\n\"help:Prints this message or the help of the given subcommand(s)\" \\\n    )\n    _describe -t commands 'ffsend commands' commands \"$@\"\n}\n(( $+functions[_ffsend__complete_commands] )) ||\n_ffsend__complete_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend complete commands' commands \"$@\"\n}\n(( $+functions[_ffsend__generate__complete_commands] )) ||\n_ffsend__generate__complete_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend generate complete commands' commands \"$@\"\n}\n(( $+functions[_ffsend__completion_commands] )) ||\n_ffsend__completion_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend completion commands' commands \"$@\"\n}\n(( $+functions[_ffsend__generate__completion_commands] )) ||\n_ffsend__generate__completion_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend generate completion commands' commands \"$@\"\n}\n(( $+functions[_ffsend__generate__completions_commands] )) ||\n_ffsend__generate__completions_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend generate completions commands' commands \"$@\"\n}\n(( $+functions[_d_commands] )) ||\n_d_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'd commands' commands \"$@\"\n}\n(( $+functions[_ffsend__d_commands] )) ||\n_ffsend__d_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend d commands' commands \"$@\"\n}\n(( $+functions[_dbg_commands] )) ||\n_dbg_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'dbg commands' commands \"$@\"\n}\n(( $+functions[_ffsend__dbg_commands] )) ||\n_ffsend__dbg_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend dbg commands' commands \"$@\"\n}\n(( $+functions[_ffsend__debug_commands] )) ||\n_ffsend__debug_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend debug commands' commands \"$@\"\n}\n(( $+functions[_del_commands] )) ||\n_del_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'del commands' commands \"$@\"\n}\n(( $+functions[_ffsend__del_commands] )) ||\n_ffsend__del_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend del commands' commands \"$@\"\n}\n(( $+functions[_ffsend__delete_commands] )) ||\n_ffsend__delete_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend delete commands' commands \"$@\"\n}\n(( $+functions[_down_commands] )) ||\n_down_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'down commands' commands \"$@\"\n}\n(( $+functions[_ffsend__down_commands] )) ||\n_ffsend__down_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend down commands' commands \"$@\"\n}\n(( $+functions[_ffsend__download_commands] )) ||\n_ffsend__download_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend download commands' commands \"$@\"\n}\n(( $+functions[_e_commands] )) ||\n_e_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'e commands' commands \"$@\"\n}\n(( $+functions[_ffsend__e_commands] )) ||\n_ffsend__e_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend e commands' commands \"$@\"\n}\n(( $+functions[_exist_commands] )) ||\n_exist_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'exist commands' commands \"$@\"\n}\n(( $+functions[_ffsend__exist_commands] )) ||\n_ffsend__exist_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend exist commands' commands \"$@\"\n}\n(( $+functions[_ffsend__exists_commands] )) ||\n_ffsend__exists_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend exists commands' commands \"$@\"\n}\n(( $+functions[_gen_commands] )) ||\n_gen_commands() {\n    local commands; commands=(\n        \"completions:Shell completions\" \\\n\"help:Prints this message or the help of the given subcommand(s)\" \\\n    )\n    _describe -t commands 'gen commands' commands \"$@\"\n}\n(( $+functions[_ffsend__generate_commands] )) ||\n_ffsend__generate_commands() {\n    local commands; commands=(\n        \"completions:Shell completions\" \\\n\"help:Prints this message or the help of the given subcommand(s)\" \\\n    )\n    _describe -t commands 'ffsend generate commands' commands \"$@\"\n}\n(( $+functions[_ffsend__h_commands] )) ||\n_ffsend__h_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend h commands' commands \"$@\"\n}\n(( $+functions[_h_commands] )) ||\n_h_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'h commands' commands \"$@\"\n}\n(( $+functions[_ffsend__generate__help_commands] )) ||\n_ffsend__generate__help_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend generate help commands' commands \"$@\"\n}\n(( $+functions[_ffsend__help_commands] )) ||\n_ffsend__help_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend help commands' commands \"$@\"\n}\n(( $+functions[_ffsend__history_commands] )) ||\n_ffsend__history_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend history commands' commands \"$@\"\n}\n(( $+functions[_ffsend__i_commands] )) ||\n_ffsend__i_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend i commands' commands \"$@\"\n}\n(( $+functions[_i_commands] )) ||\n_i_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'i commands' commands \"$@\"\n}\n(( $+functions[_ffsend__info_commands] )) ||\n_ffsend__info_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend info commands' commands \"$@\"\n}\n(( $+functions[_ffsend__information_commands] )) ||\n_ffsend__information_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend information commands' commands \"$@\"\n}\n(( $+functions[_information_commands] )) ||\n_information_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'information commands' commands \"$@\"\n}\n(( $+functions[_ffsend__ls_commands] )) ||\n_ffsend__ls_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend ls commands' commands \"$@\"\n}\n(( $+functions[_ls_commands] )) ||\n_ls_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ls commands' commands \"$@\"\n}\n(( $+functions[_ffsend__p_commands] )) ||\n_ffsend__p_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend p commands' commands \"$@\"\n}\n(( $+functions[_p_commands] )) ||\n_p_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'p commands' commands \"$@\"\n}\n(( $+functions[_ffsend__param_commands] )) ||\n_ffsend__param_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend param commands' commands \"$@\"\n}\n(( $+functions[_param_commands] )) ||\n_param_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'param commands' commands \"$@\"\n}\n(( $+functions[_ffsend__parameter_commands] )) ||\n_ffsend__parameter_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend parameter commands' commands \"$@\"\n}\n(( $+functions[_parameter_commands] )) ||\n_parameter_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'parameter commands' commands \"$@\"\n}\n(( $+functions[_ffsend__parameters_commands] )) ||\n_ffsend__parameters_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend parameters commands' commands \"$@\"\n}\n(( $+functions[_ffsend__params_commands] )) ||\n_ffsend__params_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend params commands' commands \"$@\"\n}\n(( $+functions[_params_commands] )) ||\n_params_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'params commands' commands \"$@\"\n}\n(( $+functions[_ffsend__pass_commands] )) ||\n_ffsend__pass_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend pass commands' commands \"$@\"\n}\n(( $+functions[_pass_commands] )) ||\n_pass_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'pass commands' commands \"$@\"\n}\n(( $+functions[_ffsend__password_commands] )) ||\n_ffsend__password_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend password commands' commands \"$@\"\n}\n(( $+functions[_ffsend__rm_commands] )) ||\n_ffsend__rm_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend rm commands' commands \"$@\"\n}\n(( $+functions[_rm_commands] )) ||\n_rm_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'rm commands' commands \"$@\"\n}\n(( $+functions[_ffsend__u_commands] )) ||\n_ffsend__u_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend u commands' commands \"$@\"\n}\n(( $+functions[_u_commands] )) ||\n_u_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'u commands' commands \"$@\"\n}\n(( $+functions[_ffsend__up_commands] )) ||\n_ffsend__up_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend up commands' commands \"$@\"\n}\n(( $+functions[_up_commands] )) ||\n_up_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'up commands' commands \"$@\"\n}\n(( $+functions[_ffsend__upload_commands] )) ||\n_ffsend__upload_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend upload commands' commands \"$@\"\n}\n(( $+functions[_ffsend__v_commands] )) ||\n_ffsend__v_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend v commands' commands \"$@\"\n}\n(( $+functions[_v_commands] )) ||\n_v_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'v commands' commands \"$@\"\n}\n(( $+functions[_ffsend__ver_commands] )) ||\n_ffsend__ver_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend ver commands' commands \"$@\"\n}\n(( $+functions[_ver_commands] )) ||\n_ver_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ver commands' commands \"$@\"\n}\n(( $+functions[_ffsend__version_commands] )) ||\n_ffsend__version_commands() {\n    local commands; commands=(\n        \n    )\n    _describe -t commands 'ffsend version commands' commands \"$@\"\n}\n\n_ffsend \"$@\""
  },
  {
    "path": "contrib/completions/_ffsend.ps1",
    "content": "\nusing namespace System.Management.Automation\nusing namespace System.Management.Automation.Language\n\nRegister-ArgumentCompleter -Native -CommandName 'ffsend' -ScriptBlock {\n    param($wordToComplete, $commandAst, $cursorPosition)\n\n    $commandElements = $commandAst.CommandElements\n    $command = @(\n        'ffsend'\n        for ($i = 1; $i -lt $commandElements.Count; $i++) {\n            $element = $commandElements[$i]\n            if ($element -isnot [StringConstantExpressionAst] -or\n                $element.StringConstantType -ne [StringConstantType]::BareWord -or\n                $element.Value.StartsWith('-')) {\n                break\n        }\n        $element.Value\n    }) -join ';'\n\n    $completions = @(switch ($command) {\n        'ffsend' {\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('debug', 'debug', [CompletionResultType]::ParameterValue, 'View debug information')\n            [CompletionResult]::new('delete', 'delete', [CompletionResultType]::ParameterValue, 'Delete a shared file')\n            [CompletionResult]::new('download', 'download', [CompletionResultType]::ParameterValue, 'Download files')\n            [CompletionResult]::new('exists', 'exists', [CompletionResultType]::ParameterValue, 'Check whether a remote file exists')\n            [CompletionResult]::new('generate', 'generate', [CompletionResultType]::ParameterValue, 'Generate assets')\n            [CompletionResult]::new('info', 'info', [CompletionResultType]::ParameterValue, 'Fetch info about a shared file')\n            [CompletionResult]::new('parameters', 'parameters', [CompletionResultType]::ParameterValue, 'Change parameters of a shared file')\n            [CompletionResult]::new('password', 'password', [CompletionResultType]::ParameterValue, 'Change the password of a shared file')\n            [CompletionResult]::new('upload', 'upload', [CompletionResultType]::ParameterValue, 'Upload files')\n            [CompletionResult]::new('version', 'version', [CompletionResultType]::ParameterValue, 'Determine the Send server version')\n            [CompletionResult]::new('history', 'history', [CompletionResultType]::ParameterValue, 'View file history')\n            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Prints this message or the help of the given subcommand(s)')\n            break\n        }\n        'ffsend;debug' {\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;delete' {\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('--owner', 'owner', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;download' {\n            [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Unlock a password protected file')\n            [CompletionResult]::new('--password', 'password', [CompletionResultType]::ParameterName, 'Unlock a password protected file')\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Output file or directory')\n            [CompletionResult]::new('--output', 'output', [CompletionResultType]::ParameterName, 'Output file or directory')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Extract an archived file')\n            [CompletionResult]::new('--extract', 'extract', [CompletionResultType]::ParameterName, 'Extract an archived file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;exists' {\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;generate' {\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('completions', 'completions', [CompletionResultType]::ParameterValue, 'Shell completions')\n            [CompletionResult]::new('help', 'help', [CompletionResultType]::ParameterValue, 'Prints this message or the help of the given subcommand(s)')\n            break\n        }\n        'ffsend;generate;completions' {\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Shell completion files output directory')\n            [CompletionResult]::new('--output', 'output', [CompletionResultType]::ParameterName, 'Shell completion files output directory')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;generate;help' {\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;info' {\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('--owner', 'owner', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Unlock a password protected file')\n            [CompletionResult]::new('--password', 'password', [CompletionResultType]::ParameterName, 'Unlock a password protected file')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;parameters' {\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('--owner', 'owner', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'The file download limit')\n            [CompletionResult]::new('--download-limit', 'download-limit', [CompletionResultType]::ParameterName, 'The file download limit')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;password' {\n            [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Specify a password, do not prompt')\n            [CompletionResult]::new('--password', 'password', [CompletionResultType]::ParameterName, 'Specify a password, do not prompt')\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('--owner', 'owner', [CompletionResultType]::ParameterName, 'Specify the file owner token')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-P', 'P', [CompletionResultType]::ParameterName, 'Protect the file with a generated passphrase')\n            [CompletionResult]::new('--gen-passphrase', 'gen-passphrase', [CompletionResultType]::ParameterName, 'Protect the file with a generated passphrase')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;upload' {\n            [CompletionResult]::new('-p', 'p', [CompletionResultType]::ParameterName, 'Protect the file with a password')\n            [CompletionResult]::new('--password', 'password', [CompletionResultType]::ParameterName, 'Protect the file with a password')\n            [CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'The file download limit')\n            [CompletionResult]::new('--download-limit', 'download-limit', [CompletionResultType]::ParameterName, 'The file download limit')\n            [CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'The file expiry time')\n            [CompletionResult]::new('--expiry-time', 'expiry-time', [CompletionResultType]::ParameterName, 'The file expiry time')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('-n', 'n', [CompletionResultType]::ParameterName, 'Rename the file being uploaded')\n            [CompletionResult]::new('--name', 'name', [CompletionResultType]::ParameterName, 'Rename the file being uploaded')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-P', 'P', [CompletionResultType]::ParameterName, 'Protect the file with a generated passphrase')\n            [CompletionResult]::new('--gen-passphrase', 'gen-passphrase', [CompletionResultType]::ParameterName, 'Protect the file with a generated passphrase')\n            [CompletionResult]::new('-o', 'o', [CompletionResultType]::ParameterName, 'Open the share link in your browser')\n            [CompletionResult]::new('--open', 'open', [CompletionResultType]::ParameterName, 'Open the share link in your browser')\n            [CompletionResult]::new('-D', 'D', [CompletionResultType]::ParameterName, 'Delete local file after upload')\n            [CompletionResult]::new('--delete', 'delete', [CompletionResultType]::ParameterName, 'Delete local file after upload')\n            [CompletionResult]::new('-a', 'a', [CompletionResultType]::ParameterName, 'Archive the upload in a single file')\n            [CompletionResult]::new('--archive', 'archive', [CompletionResultType]::ParameterName, 'Archive the upload in a single file')\n            [CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'Copy the share link to your clipboard')\n            [CompletionResult]::new('--copy', 'copy', [CompletionResultType]::ParameterName, 'Copy the share link to your clipboard')\n            [CompletionResult]::new('-C', 'C', [CompletionResultType]::ParameterName, 'Copy the ffsend download command to your clipboard')\n            [CompletionResult]::new('--copy-cmd', 'copy-cmd', [CompletionResultType]::ParameterName, 'Copy the ffsend download command to your clipboard')\n            [CompletionResult]::new('-S', 'S', [CompletionResultType]::ParameterName, 'Shorten share URLs with a public service')\n            [CompletionResult]::new('--shorten', 'shorten', [CompletionResultType]::ParameterName, 'Shorten share URLs with a public service')\n            [CompletionResult]::new('-Q', 'Q', [CompletionResultType]::ParameterName, 'Print a QR code for the share URL')\n            [CompletionResult]::new('--qrcode', 'qrcode', [CompletionResultType]::ParameterName, 'Print a QR code for the share URL')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;version' {\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('--host', 'host', [CompletionResultType]::ParameterName, 'The remote host to upload to')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;history' {\n            [CompletionResult]::new('-R', 'R', [CompletionResultType]::ParameterName, 'Remove history entry')\n            [CompletionResult]::new('--rm', 'rm', [CompletionResultType]::ParameterName, 'Remove history entry')\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-C', 'C', [CompletionResultType]::ParameterName, 'Clear all history')\n            [CompletionResult]::new('--clear', 'clear', [CompletionResultType]::ParameterName, 'Clear all history')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n        'ffsend;help' {\n            [CompletionResult]::new('-t', 't', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('--timeout', 'timeout', [CompletionResultType]::ParameterName, 'Request timeout (0 to disable)')\n            [CompletionResult]::new('-T', 'T', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('--transfer-timeout', 'transfer-timeout', [CompletionResultType]::ParameterName, 'Transfer timeout (0 to disable)')\n            [CompletionResult]::new('-A', 'A', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--api', 'api', [CompletionResultType]::ParameterName, 'Server API version to use, ''-'' to lookup')\n            [CompletionResult]::new('--basic-auth', 'basic-auth', [CompletionResultType]::ParameterName, 'Protected proxy HTTP basic authentication credentials (not FxA)')\n            [CompletionResult]::new('-H', 'H', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('--history', 'history', [CompletionResultType]::ParameterName, 'Use the specified history file')\n            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Prints help information')\n            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Prints version information')\n            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('--force', 'force', [CompletionResultType]::ParameterName, 'Force the action, ignore warnings')\n            [CompletionResult]::new('-I', 'I', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('--no-interact', 'no-interact', [CompletionResultType]::ParameterName, 'Not interactive, do not prompt')\n            [CompletionResult]::new('-y', 'y', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('--yes', 'yes', [CompletionResultType]::ParameterName, 'Assume yes for prompts')\n            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Produce output suitable for logging and automation')\n            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Enable verbose information and logging')\n            [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            [CompletionResult]::new('--incognito', 'incognito', [CompletionResultType]::ParameterName, 'Don''t update local history for actions')\n            break\n        }\n    })\n\n    $completions.Where{ $_.CompletionText -like \"$wordToComplete*\" } |\n        Sort-Object -Property ListItemText\n}\n"
  },
  {
    "path": "contrib/completions/ffsend.bash",
    "content": "_ffsend() {\n    local i cur prev opts cmds\n    COMPREPLY=()\n    cur=\"${COMP_WORDS[COMP_CWORD]}\"\n    prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n    cmd=\"\"\n    opts=\"\"\n\n    for i in ${COMP_WORDS[@]}\n    do\n        case \"${i}\" in\n            ffsend)\n                cmd=\"ffsend\"\n                ;;\n            \n            complete)\n                cmd+=\"__complete\"\n                ;;\n            completion)\n                cmd+=\"__completion\"\n                ;;\n            completions)\n                cmd+=\"__completions\"\n                ;;\n            d)\n                cmd+=\"__d\"\n                ;;\n            dbg)\n                cmd+=\"__dbg\"\n                ;;\n            debug)\n                cmd+=\"__debug\"\n                ;;\n            del)\n                cmd+=\"__del\"\n                ;;\n            delete)\n                cmd+=\"__delete\"\n                ;;\n            down)\n                cmd+=\"__down\"\n                ;;\n            download)\n                cmd+=\"__download\"\n                ;;\n            e)\n                cmd+=\"__e\"\n                ;;\n            exist)\n                cmd+=\"__exist\"\n                ;;\n            exists)\n                cmd+=\"__exists\"\n                ;;\n            gen)\n                cmd+=\"__gen\"\n                ;;\n            generate)\n                cmd+=\"__generate\"\n                ;;\n            h)\n                cmd+=\"__h\"\n                ;;\n            help)\n                cmd+=\"__help\"\n                ;;\n            history)\n                cmd+=\"__history\"\n                ;;\n            i)\n                cmd+=\"__i\"\n                ;;\n            info)\n                cmd+=\"__info\"\n                ;;\n            information)\n                cmd+=\"__information\"\n                ;;\n            ls)\n                cmd+=\"__ls\"\n                ;;\n            p)\n                cmd+=\"__p\"\n                ;;\n            param)\n                cmd+=\"__param\"\n                ;;\n            parameter)\n                cmd+=\"__parameter\"\n                ;;\n            parameters)\n                cmd+=\"__parameters\"\n                ;;\n            params)\n                cmd+=\"__params\"\n                ;;\n            pass)\n                cmd+=\"__pass\"\n                ;;\n            password)\n                cmd+=\"__password\"\n                ;;\n            rm)\n                cmd+=\"__rm\"\n                ;;\n            u)\n                cmd+=\"__u\"\n                ;;\n            up)\n                cmd+=\"__up\"\n                ;;\n            upload)\n                cmd+=\"__upload\"\n                ;;\n            v)\n                cmd+=\"__v\"\n                ;;\n            ver)\n                cmd+=\"__ver\"\n                ;;\n            version)\n                cmd+=\"__version\"\n                ;;\n            *)\n                ;;\n        esac\n    done\n\n    case \"${cmd}\" in\n        ffsend)\n            opts=\" -f -I -y -q -v -i -h -V -t -T -A -H  --force --no-interact --yes --quiet --verbose --incognito --help --version --timeout --transfer-timeout --api --basic-auth --history   debug delete download exists generate info parameters password upload version history help  dbg  del rm  d down  e exist  gen  i information  params param parameter  pass p  u up  ver v  h ls\"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        \n        ffsend__d)\n            opts=\" -e -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --extract --help --version --force --no-interact --yes --quiet --verbose --incognito --password --output --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__dbg)\n            opts=\" -V -f -I -y -q -v -i -h -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --host --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__debug)\n            opts=\" -V -f -I -y -q -v -i -h -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --host --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__del)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__delete)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__down)\n            opts=\" -e -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --extract --help --version --force --no-interact --yes --quiet --verbose --incognito --password --output --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__download)\n            opts=\" -e -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --extract --help --version --force --no-interact --yes --quiet --verbose --incognito --password --output --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__e)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__exist)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__exists)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__gen)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history   completions help  completion complete\"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__generate)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history   completions help  completion complete\"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__generate__complete)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --output --timeout --transfer-timeout --api --basic-auth --history  <SHELL>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__generate__completion)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --output --timeout --transfer-timeout --api --basic-auth --history  <SHELL>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__generate__completions)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --output --timeout --transfer-timeout --api --basic-auth --history  <SHELL>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --output)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__generate__help)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__h)\n            opts=\" -C -h -V -f -I -y -q -v -i -R -t -T -A -H  --clear --help --version --force --no-interact --yes --quiet --verbose --incognito --rm --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --rm)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -R)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__help)\n            opts=\" -h -V -f -I -y -q -v -i -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__history)\n            opts=\" -C -h -V -f -I -y -q -v -i -R -t -T -A -H  --clear --help --version --force --no-interact --yes --quiet --verbose --incognito --rm --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --rm)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -R)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__i)\n            opts=\" -h -V -f -I -y -q -v -i -o -p -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --password --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__info)\n            opts=\" -h -V -f -I -y -q -v -i -o -p -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --password --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__information)\n            opts=\" -h -V -f -I -y -q -v -i -o -p -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --password --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__ls)\n            opts=\" -C -h -V -f -I -y -q -v -i -R -t -T -A -H  --clear --help --version --force --no-interact --yes --quiet --verbose --incognito --rm --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --rm)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -R)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__p)\n            opts=\" -P -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --gen-passphrase --help --version --force --no-interact --yes --quiet --verbose --incognito --password --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__param)\n            opts=\" -h -V -f -I -y -q -v -i -o -d -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --download-limit --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__parameter)\n            opts=\" -h -V -f -I -y -q -v -i -o -d -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --download-limit --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__parameters)\n            opts=\" -h -V -f -I -y -q -v -i -o -d -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --download-limit --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__params)\n            opts=\" -h -V -f -I -y -q -v -i -o -d -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --download-limit --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__pass)\n            opts=\" -P -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --gen-passphrase --help --version --force --no-interact --yes --quiet --verbose --incognito --password --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__password)\n            opts=\" -P -h -V -f -I -y -q -v -i -p -o -t -T -A -H  --gen-passphrase --help --version --force --no-interact --yes --quiet --verbose --incognito --password --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__rm)\n            opts=\" -h -V -f -I -y -q -v -i -o -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --owner --timeout --transfer-timeout --api --basic-auth --history  <URL> \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --owner)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -o)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__u)\n            opts=\" -P -o -D -a -c -C -S -Q -V -f -I -y -q -v -i -p -d -e -h -n -t -T -A -H  --gen-passphrase --open --delete --archive --copy --copy-cmd --shorten --qrcode --help --version --force --no-interact --yes --quiet --verbose --incognito --password --download-limit --expiry-time --host --name --timeout --transfer-timeout --api --basic-auth --history  <FILE>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --expiry-time)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -e)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --name)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -n)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__up)\n            opts=\" -P -o -D -a -c -C -S -Q -V -f -I -y -q -v -i -p -d -e -h -n -t -T -A -H  --gen-passphrase --open --delete --archive --copy --copy-cmd --shorten --qrcode --help --version --force --no-interact --yes --quiet --verbose --incognito --password --download-limit --expiry-time --host --name --timeout --transfer-timeout --api --basic-auth --history  <FILE>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --expiry-time)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -e)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --name)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -n)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__upload)\n            opts=\" -P -o -D -a -c -C -S -Q -V -f -I -y -q -v -i -p -d -e -h -n -t -T -A -H  --gen-passphrase --open --delete --archive --copy --copy-cmd --shorten --qrcode --help --version --force --no-interact --yes --quiet --verbose --incognito --password --download-limit --expiry-time --host --name --timeout --transfer-timeout --api --basic-auth --history  <FILE>... \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --password)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -p)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --download-limit)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -d)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --expiry-time)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -e)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --name)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -n)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__v)\n            opts=\" -V -f -I -y -q -v -i -h -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --host --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__ver)\n            opts=\" -V -f -I -y -q -v -i -h -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --host --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n        ffsend__version)\n            opts=\" -V -f -I -y -q -v -i -h -t -T -A -H  --help --version --force --no-interact --yes --quiet --verbose --incognito --host --timeout --transfer-timeout --api --basic-auth --history  \"\n            if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then\n                COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n                return 0\n            fi\n            case \"${prev}\" in\n                \n                --host)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -h)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -t)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --transfer-timeout)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -T)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --api)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -A)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --basic-auth)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                --history)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                    -H)\n                    COMPREPLY=($(compgen -f \"${cur}\"))\n                    return 0\n                    ;;\n                *)\n                    COMPREPLY=()\n                    ;;\n            esac\n            COMPREPLY=( $(compgen -W \"${opts}\" -- \"${cur}\") )\n            return 0\n            ;;\n    esac\n}\n\ncomplete -F _ffsend -o bashdefault -o default ffsend\n"
  },
  {
    "path": "contrib/completions/ffsend.elv",
    "content": "\nedit:completion:arg-completer[ffsend] = [@words]{\n    fn spaces [n]{\n        repeat $n ' ' | joins ''\n    }\n    fn cand [text desc]{\n        edit:complex-candidate $text &display-suffix=' '(spaces (- 14 (wcswidth $text)))$desc\n    }\n    command = 'ffsend'\n    for word $words[1:-1] {\n        if (has-prefix $word '-') {\n            break\n        }\n        command = $command';'$word\n    }\n    completions = [\n        &'ffsend'= {\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand debug 'View debug information'\n            cand delete 'Delete a shared file'\n            cand download 'Download files'\n            cand exists 'Check whether a remote file exists'\n            cand generate 'Generate assets'\n            cand info 'Fetch info about a shared file'\n            cand parameters 'Change parameters of a shared file'\n            cand password 'Change the password of a shared file'\n            cand upload 'Upload files'\n            cand version 'Determine the Send server version'\n            cand history 'View file history'\n            cand help 'Prints this message or the help of the given subcommand(s)'\n        }\n        &'ffsend;debug'= {\n            cand -h 'The remote host to upload to'\n            cand --host 'The remote host to upload to'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;delete'= {\n            cand -o 'Specify the file owner token'\n            cand --owner 'Specify the file owner token'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;download'= {\n            cand -p 'Unlock a password protected file'\n            cand --password 'Unlock a password protected file'\n            cand -o 'Output file or directory'\n            cand --output 'Output file or directory'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -e 'Extract an archived file'\n            cand --extract 'Extract an archived file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;exists'= {\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;generate'= {\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n            cand completions 'Shell completions'\n            cand help 'Prints this message or the help of the given subcommand(s)'\n        }\n        &'ffsend;generate;completions'= {\n            cand -o 'Shell completion files output directory'\n            cand --output 'Shell completion files output directory'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;generate;help'= {\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;info'= {\n            cand -o 'Specify the file owner token'\n            cand --owner 'Specify the file owner token'\n            cand -p 'Unlock a password protected file'\n            cand --password 'Unlock a password protected file'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;parameters'= {\n            cand -o 'Specify the file owner token'\n            cand --owner 'Specify the file owner token'\n            cand -d 'The file download limit'\n            cand --download-limit 'The file download limit'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;password'= {\n            cand -p 'Specify a password, do not prompt'\n            cand --password 'Specify a password, do not prompt'\n            cand -o 'Specify the file owner token'\n            cand --owner 'Specify the file owner token'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -P 'Protect the file with a generated passphrase'\n            cand --gen-passphrase 'Protect the file with a generated passphrase'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;upload'= {\n            cand -p 'Protect the file with a password'\n            cand --password 'Protect the file with a password'\n            cand -d 'The file download limit'\n            cand --download-limit 'The file download limit'\n            cand -e 'The file expiry time'\n            cand --expiry-time 'The file expiry time'\n            cand -h 'The remote host to upload to'\n            cand --host 'The remote host to upload to'\n            cand -n 'Rename the file being uploaded'\n            cand --name 'Rename the file being uploaded'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -P 'Protect the file with a generated passphrase'\n            cand --gen-passphrase 'Protect the file with a generated passphrase'\n            cand -o 'Open the share link in your browser'\n            cand --open 'Open the share link in your browser'\n            cand -D 'Delete local file after upload'\n            cand --delete 'Delete local file after upload'\n            cand -a 'Archive the upload in a single file'\n            cand --archive 'Archive the upload in a single file'\n            cand -c 'Copy the share link to your clipboard'\n            cand --copy 'Copy the share link to your clipboard'\n            cand -C 'Copy the ffsend download command to your clipboard'\n            cand --copy-cmd 'Copy the ffsend download command to your clipboard'\n            cand -S 'Shorten share URLs with a public service'\n            cand --shorten 'Shorten share URLs with a public service'\n            cand -Q 'Print a QR code for the share URL'\n            cand --qrcode 'Print a QR code for the share URL'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;version'= {\n            cand -h 'The remote host to upload to'\n            cand --host 'The remote host to upload to'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;history'= {\n            cand -R 'Remove history entry'\n            cand --rm 'Remove history entry'\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -C 'Clear all history'\n            cand --clear 'Clear all history'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n        &'ffsend;help'= {\n            cand -t 'Request timeout (0 to disable)'\n            cand --timeout 'Request timeout (0 to disable)'\n            cand -T 'Transfer timeout (0 to disable)'\n            cand --transfer-timeout 'Transfer timeout (0 to disable)'\n            cand -A 'Server API version to use, ''-'' to lookup'\n            cand --api 'Server API version to use, ''-'' to lookup'\n            cand --basic-auth 'Protected proxy HTTP basic authentication credentials (not FxA)'\n            cand -H 'Use the specified history file'\n            cand --history 'Use the specified history file'\n            cand -h 'Prints help information'\n            cand --help 'Prints help information'\n            cand -V 'Prints version information'\n            cand --version 'Prints version information'\n            cand -f 'Force the action, ignore warnings'\n            cand --force 'Force the action, ignore warnings'\n            cand -I 'Not interactive, do not prompt'\n            cand --no-interact 'Not interactive, do not prompt'\n            cand -y 'Assume yes for prompts'\n            cand --yes 'Assume yes for prompts'\n            cand -q 'Produce output suitable for logging and automation'\n            cand --quiet 'Produce output suitable for logging and automation'\n            cand -v 'Enable verbose information and logging'\n            cand --verbose 'Enable verbose information and logging'\n            cand -i 'Don''t update local history for actions'\n            cand --incognito 'Don''t update local history for actions'\n        }\n    ]\n    $completions[$command]\n}\n"
  },
  {
    "path": "contrib/completions/ffsend.fish",
    "content": "complete -c ffsend -n \"__fish_use_subcommand\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"debug\" -d 'View debug information'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"delete\" -d 'Delete a shared file'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"download\" -d 'Download files'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"exists\" -d 'Check whether a remote file exists'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"generate\" -d 'Generate assets'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"info\" -d 'Fetch info about a shared file'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"parameters\" -d 'Change parameters of a shared file'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"password\" -d 'Change the password of a shared file'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"upload\" -d 'Upload files'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"version\" -d 'Determine the Send server version'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"history\" -d 'View file history'\ncomplete -c ffsend -n \"__fish_use_subcommand\" -f -a \"help\" -d 'Prints this message or the help of the given subcommand(s)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s h -l host -d 'The remote host to upload to'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from debug\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s o -l owner -d 'Specify the file owner token'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from delete\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s p -l password -d 'Unlock a password protected file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s o -l output -d 'Output file or directory'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s e -l extract -d 'Extract an archived file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from download\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from exists\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -f -a \"completions\" -d 'Shell completions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from generate\" -f -a \"help\" -d 'Prints this message or the help of the given subcommand(s)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s o -l output -d 'Shell completion files output directory'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from completions\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s o -l owner -d 'Specify the file owner token'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s p -l password -d 'Unlock a password protected file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from info\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s o -l owner -d 'Specify the file owner token'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s d -l download-limit -d 'The file download limit'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from parameters\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s p -l password -d 'Specify a password, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s o -l owner -d 'Specify the file owner token'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s P -l gen-passphrase -d 'Protect the file with a generated passphrase'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from password\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s p -l password -d 'Protect the file with a password'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s d -l download-limit -d 'The file download limit'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s e -l expiry-time -d 'The file expiry time'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s h -l host -d 'The remote host to upload to'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s n -l name -d 'Rename the file being uploaded'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s P -l gen-passphrase -d 'Protect the file with a generated passphrase'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s o -l open -d 'Open the share link in your browser'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s D -l delete -d 'Delete local file after upload'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s a -l archive -d 'Archive the upload in a single file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s c -l copy -d 'Copy the share link to your clipboard'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s C -l copy-cmd -d 'Copy the ffsend download command to your clipboard'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s S -l shorten -d 'Shorten share URLs with a public service'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s Q -l qrcode -d 'Print a QR code for the share URL'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from upload\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s h -l host -d 'The remote host to upload to'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from version\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s R -l rm -d 'Remove history entry'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s C -l clear -d 'Clear all history'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from history\" -s i -l incognito -d 'Don\\'t update local history for actions'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s t -l timeout -d 'Request timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s T -l transfer-timeout -d 'Transfer timeout (0 to disable)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s A -l api -d 'Server API version to use, \\'-\\' to lookup'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -l basic-auth -d 'Protected proxy HTTP basic authentication credentials (not FxA)'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s H -l history -d 'Use the specified history file'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s h -l help -d 'Prints help information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s V -l version -d 'Prints version information'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s f -l force -d 'Force the action, ignore warnings'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s I -l no-interact -d 'Not interactive, do not prompt'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s y -l yes -d 'Assume yes for prompts'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s q -l quiet -d 'Produce output suitable for logging and automation'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s v -l verbose -d 'Enable verbose information and logging'\ncomplete -c ffsend -n \"__fish_seen_subcommand_from help\" -s i -l incognito -d 'Don\\'t update local history for actions'\n"
  },
  {
    "path": "contrib/completions/gen_completions",
    "content": "#!/usr/bin/env bash\n\n# Stop on error\nset -e\n\necho \"Generating all completions using cargo debug binary...\"\ncargo run -q -- generate completions all --output \"$PWD\"\necho \"Done.\"\n"
  },
  {
    "path": "contrib/util/nautilus/README.md",
    "content": "`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.\n\n* Copy the `firefox-send` file to ~/.local/share/nautilus/scripts/firefox-send\n* Modify the default options to your use case: host server, download number, retention time.\n* Make the file executable (`chmod +x firefox-send`).\n* Restart Nautilus/Nemo/Caja.\n"
  },
  {
    "path": "contrib/util/nautilus/firefox-send",
    "content": "#!/bin/bash\n\n\n#CONSTANTS\n#FILEPATH=`echo $NAUTILUS_SCRIPT_SELECTED_URIS | sed 's@file://@@g'`\n# Quote the paths\nIFS=$'\\n' read -d '' -r -a FILEPATH <<< \"$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS\"\nFFSEND_BIN='/usr/bin/ffsend'\nFFSEND_BIN_OPTS=\"upload --open --copy\"\nZENITY='/usr/bin/zenity '\nZENITY_PROGRESS_OPTIONS='--auto-close --auto-kill' #you can remove this if you like\n\n#sanity checks\nfor sanity_check in $FFSEND_BIN \"${FILEPATH[@]}\"\ndo\n   ZENITY_ERROR_SANITY=\"There is an error, it involved $sanity_check.\\n Probably binary or file missing\" \n   if [ ! -e $sanity_check ]\n     then \n      #zenity --error --text=\"$(eval \"echo \\\"$ZENITY_ERROR_SANITY\\\"\")\"\n      zenity --error --text=\"$ZENITY_ERROR_SANITY\"\n     exit \n  fi\ndone\n\n# Use the following flags automatically from now on\n# -I: no interaction\n# -f: force\n# -y: yes\n# -q: quiet\nexport FFSEND_NO_INTERACT=1 FFSEND_FORCE=1 FFSEND_YES=1 FFSEND_QUIET=1\nexport FFSEND_HOST=https://send.boblorange.net\nexport FFSEND_EXPIRY_TIME=604800\nexport FFSEND_DOWNLOAD_LIMIT=5\n\n#check whether copying file or directory\nif [ ! -f \"${FILEPATH[@]}\" ]; then\n    FFSEND_BIN_OPTS=\"$FFSEND_BIN_OPTS --archive\"\nfi\n  \n# Upload a file\n#zenity --info --text=\"Ready to send: $FFSEND_BIN $FFSEND_BIN_OPTS ${FILEPATH[@]}\"\n$FFSEND_BIN $FFSEND_BIN_OPTS \"${FILEPATH[@]}\" | $($ZENITY --progress --text=\"sending $(basename $FILEPATH)\" --pulsate   $ZENITY_PROGRESS_OPTIONS) \n#echo -e \"$FILEPATH\" | xargs -i $FFSEND_BIN $FFSEND_BIN_OPTS {} | $($ZENITY --progress --text=\"sending $(basename $FILEPATH)\" --pulsate   $ZENITY_PROGRESS_OPTIONS) \n\n# Upload a file\n#echo -e \"$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS\" | xargs -i ffsend upload --open --copy {}\n"
  },
  {
    "path": "pkg/alpine/APKBUILD",
    "content": "# Contributor: Rasmus Thomsen <oss@cogitri.dev>\n# Maintainer: Rasmus Thomsen <oss@cogitri.dev>\npkgname=ffsend\npkgver=0.2.62\npkgrel=0\npkgdesc=\" A fully featured Send client\"\nurl=\"https://gitlab.com/timvisee/ffsend\"\narch=\"x86_64 x86 armhf armv7 aarch64 ppc64le\" # limited by cargo\nlicense=\"GPL-3.0-only\"\nmakedepends=\"cargo openssl-dev\"\nsubpackages=\"\n\t$pkgname-zsh-completion:zshcomp:noarch\n\t$pkgname-fish-completion:fishcomp:noarch\n\t$pkgname-bash-completion:bashcomp:noarch\n\t\"\nsource=\"https://gitlab.com/timvisee/ffsend/-/archive/v$pkgver/ffsend-v$pkgver.tar.gz\"\nbuilddir=\"$srcdir/$pkgname-v$pkgver\"\n\ncase \"$CARCH\" in\n\tx86)\n\t\texport CFLAGS=\"$CFLAGS -fno-stack-protector\"\n\t\t;;\nesac\n\nbuild() {\n\tcargo build --release\n}\n\ncheck() {\n\tcargo test --release\n}\n\npackage() {\n\tcargo install --path . --root=\"$pkgdir/usr\"\n\trm \"$pkgdir\"/usr/.crates.toml\n}\n\nbashcomp() {\n\tdepends=\"\"\n\tpkgdesc=\"Bash completions for $pkgname\"\n\tinstall_if=\"$pkgname=$pkgver-r$pkgrel bash-completion\"\n\n\tinstall -Dm644 \"$builddir\"/contrib/completions/ffsend.bash \\\n\t\t\t\"$subpkgdir\"/usr/share/bash-completion/completions/ffsend\n}\n\nzshcomp() {\n\tdepends=\"\"\n\tpkgdesc=\"Zsh compltions for $pkgname\"\n\tinstall_if=\"$pkgname=$pkgver-r$pkgrel zsh\"\n\n\tinstall -Dm644 \"$builddir\"/contrib/completions/_ffsend \\\n\t\t\t\"$subpkgdir\"/usr/share/zsh/site-functions/_ffsend\n}\n\nfishcomp() {\n\tdepends=\"\"\n\tpkgdesc=\"Fish completions for $pkgname\"\n\tinstall_if=\"$pkgname=$pkgver-r$pkgrel fish\"\n\n\tinstall -Dm644 \"$builddir\"/contrib/completions/ffsend.fish \\\n\t\t\t\"$subpkgdir\"/usr/share/fish/completions/ffsend.fish\n}\n\nsha512sums=\"97477f59a498f4805340647c50c139d70ddbabaebb49b4acbae595ed9987fa2941b8d4dfd2edf76264b2a500fa10ac10f8583938fb29013936d9c092fe7fe7f1  ffsend-v0.2.51.tar.gz\"\n"
  },
  {
    "path": "pkg/aur/aur.pub",
    "content": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDHfiNi+rOCPKGLB6v9uuYR6GkN6Zd+CdaRbV82A26AUzs48ZG0xZGXHsoRuZY/yCUhcrS2u9xZ16fsAxnyf1QCF1hZVABUYtNhL1eEbSbLNiG9vIWJzbRjgegN/yyiG9ZVhFfNqXtPeapvuM3H44a2XeeFJcvTOfj/alkVjypi/DY/+XpC1IlX+CARC/e0zXHa3KZohn+CfBj8kWZWQEr7+EtKT59pslNxuJPcDUw7sKYLcBBz00BT0vv3lntyvZI1rRsD7AvItOwSZPp6or78Tgp8+O0HvFpjrlNipPEqDPpETIPcjTIVAlvlPFK1J0Rpzud38YdoWGfPiM77k7L7 timvisee@aur\n"
  },
  {
    "path": "pkg/aur/ffsend/PKGBUILD",
    "content": "# Maintainer: Tim Visee <tim@visee.me>\n#\n# This PKGBUILD is managed externally, and is automatically updated here:\n# - https://gitlab.com/timvisee/ffsend/blob/master/pkg/aur/ffsend/PKGBUILD\n# - Mirror: https://github.com/timvisee/ffsend/blob/master/pkg/aur/ffsend/PKGBUILD\n\npkgname=ffsend\npkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml\npkgrel=1\npkgdesc=\"Easily and securely share files from the command line. A Send client.\"\nurl=\"https://gitlab.com/timvisee/ffsend\"\nlicense=('GPL3')\nsource=(\"$url/-/archive/v$pkgver/ffsend-v$pkgver.tar.gz\") # automatically set in CI, see: /.gitlab-ci.yml\nsha256sums=('SKIP') # automatically set in CI, see: /.gitlab-ci.yml\narch=('x86_64' 'i686')\ndepends=('ca-certificates')\nmakedepends=('cargo' 'cmake' 'openssl>=1.0')\noptdepends=('xclip: clipboard support')\n\nprepare() {\n    cd \"$pkgname-v$pkgver\"\n\n    cargo fetch --locked --target \"$CARCH-unknown-linux-gnu\"\n}\n\nbuild() {\n    cd \"$pkgname-v$pkgver\"\n\n    export RUSTUP_TOOLCHAIN=stable\n    export CARGO_TARGET_DIR=target\n    cargo build --frozen --release\n}\n\ncheck() {\n    cd \"$pkgname-v$pkgver\"\n\n    export RUSTUP_TOOLCHAIN=stable\n    cargo test --frozen\n}\n\npackage() {\n    cd \"$pkgname-v$pkgver\"\n\n    install -Dm0755 -t \"$pkgdir/usr/bin/\" \"target/release/$pkgname\"\n\n    # Shell completions and LICENSE file\n    install -Dm644 \"contrib/completions/ffsend.bash\" \\\n        \"$pkgdir/etc/bash_completion.d/ffsend\"\n\tinstall -Dm644 \"contrib/completions/_ffsend\" \\\n        \"$pkgdir/usr/share/zsh/site-functions/_ffsend\"\n\tinstall -Dm644 \"contrib/completions/ffsend.fish\" \\\n        \"$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish\"\n    install -Dm644 \"LICENSE\" \\\n        \"$pkgdir/usr/share/licenses/ffsend/LICENSE\"\n}\n"
  },
  {
    "path": "pkg/aur/ffsend-bin/PKGBUILD",
    "content": "# Maintainer: Tim Visee <tim@visee.me>\n# Contributor: Ariel AxionL <i at axionl dot me>\n#\n# This PKGBUILD is managed externally, and is automatically updated here:\n# - https://gitlab.com/timvisee/ffsend/blob/master/pkg/aur/ffsend-bin/PKGBUILD\n# - Mirror: https://github.com/timvisee/ffsend/blob/master/pkg/aur/ffsend-bin/PKGBUILD\n\npkgname=ffsend-bin\npkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml\npkgrel=1\npkgdesc=\"Easily and securely share files from the command line. A Send client.\"\nurl=\"https://gitlab.com/timvisee/ffsend\"\nlicense=('GPL3')\nsource=(\"ffsend-v$pkgver::https://github.com/timvisee/ffsend/releases/download/v$pkgver/ffsend-v$pkgver-linux-x64-static\"\n        \"ffsend-v$pkgver.bash::https://raw.githubusercontent.com/timvisee/ffsend/v$pkgver/contrib/completions/ffsend.bash\"\n        \"ffsend-v$pkgver.zsh::https://raw.githubusercontent.com/timvisee/ffsend/v$pkgver/contrib/completions/_ffsend\"\n        \"ffsend-v$pkgver.fish::https://raw.githubusercontent.com/timvisee/ffsend/v$pkgver/contrib/completions/ffsend.fish\"\n        \"LICENSE-v$pkgver::https://raw.githubusercontent.com/timvisee/ffsend/v$pkgver/LICENSE\") # automatically set in CI, see: /.gitlab-ci.yml\nsha256sums=('SKIP')\narch=('x86_64')\nprovides=('ffsend')\nconflicts=('ffsend')\ndepends=('ca-certificates')\noptdepends=('xclip: clipboard support'\n            'bash-completion: support auto completion for bash')\n\npackage() {\n    cd \"$srcdir\"\n\n    install -Dm755 \"ffsend-v$pkgver\" \"$pkgdir/usr/bin/ffsend\"\n\n    # Shell completions and LICENSE file\n    install -Dm644 \"ffsend-v$pkgver.bash\" \"$pkgdir/usr/share/bash-completion/completions/ffsend\"\n    install -Dm644 \"ffsend-v$pkgver.zsh\" \"$pkgdir/usr/share/zsh/site-functions/_ffsend\"\n    install -Dm644 \"ffsend-v$pkgver.fish\" \"$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish\"\n    install -Dm644 \"LICENSE-v$pkgver\" \"$pkgdir/usr/share/licenses/ffsend/LICENSE\"\n}\n"
  },
  {
    "path": "pkg/aur/ffsend-git/PKGBUILD",
    "content": "# Maintainer: Tim Visee <tim@visee.me>\n#\n# This PKGBUILD is managed externally, and is automatically updated here:\n# - https://gitlab.com/timvisee/ffsend/blob/master/pkg/aur/ffsend-git/PKGBUILD\n# - Mirror: https://github.com/timvisee/ffsend/blob/master/pkg/aur/ffsend-git/PKGBUILD\n\npkgname=ffsend-git\npkgver=0.0.0 # automatically set in CI, see: /.gitlab-ci.yml\npkgrel=1\npkgdesc=\"Easily and securely share files from the command line. A Send client.\"\nurl=\"https://gitlab.com/timvisee/ffsend\"\nlicense=('GPL3')\nsource=(\"git+${url}\")\nsha256sums=('SKIP')\narch=('x86_64' 'i686')\nprovides=('ffsend')\nconflicts=('ffsend')\ndepends=('ca-certificates')\nmakedepends=('cargo' 'cmake' 'openssl>=1.0')\noptdepends=('xclip: clipboard support')\n\nprepare() {\n    cd \"${pkgname%-git}\"\n\n    cargo fetch --locked --target \"$CARCH-unknown-linux-gnu\"\n}\n\nbuild() {\n    cd \"${pkgname%-git}\"\n\n    export RUSTUP_TOOLCHAIN=stable\n    export CARGO_TARGET_DIR=target\n    cargo build --frozen --release\n}\n\ncheck() {\n    cd \"${pkgname%-git}\"\n\n    export RUSTUP_TOOLCHAIN=stable\n    cargo test --frozen\n}\n\npackage() {\n    cd \"${pkgname%-git}\"\n\n    install -Dm0755 -t \"$pkgdir/usr/bin/\" \"target/release/ffsend\"\n\n    # Shell completions and LICENSE file\n    install -Dm644 \"contrib/completions/ffsend.bash\" \\\n        \"$pkgdir/etc/bash_completion.d/ffsend\"\n\tinstall -Dm644 \"contrib/completions/_ffsend\" \\\n        \"$pkgdir/usr/share/zsh/site-functions/_ffsend\"\n\tinstall -Dm644 \"contrib/completions/ffsend.fish\" \\\n        \"$pkgdir/usr/share/fish/vendor_completions.d/ffsend.fish\"\n    install -Dm644 \"LICENSE\" \\\n        \"$pkgdir/usr/share/licenses/ffsend/LICENSE\"\n}\n"
  },
  {
    "path": "pkg/choco/ffsend/ffsend.nuspec",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<!-- Read this before creating packages: https://chocolatey.org/docs/create-packages -->\r\n<!-- It is especially important to read the above link to understand additional requirements when publishing packages to the community feed aka dot org (https://chocolatey.org/packages). -->\r\n\r\n<!-- Test your packages in a test environment: https://github.com/chocolatey/chocolatey-test-environment -->\r\n\r\n<!--\r\nThis is a nuspec. It mostly adheres to https://docs.nuget.org/create/Nuspec-Reference. Chocolatey uses a special version of NuGet.Core that allows us to do more than was initially possible. As such there are certain things to be aware of:\r\n\r\n* the package xmlns schema url may cause issues with nuget.exe\r\n* Any of the following elements can ONLY be used by choco tools - projectSourceUrl, docsUrl, mailingListUrl, bugTrackerUrl, packageSourceUrl, provides, conflicts, replaces \r\n* nuget.exe can still install packages with those elements but they are ignored. Any authoring tools or commands will error on those elements \r\n-->\r\n\r\n<!-- You can embed software files directly into packages, as long as you are not bound by distribution rights. -->\r\n<!-- * If you are an organization making private packages, you probably have no issues here -->\r\n<!-- * If you are releasing to the community feed, you need to consider distribution rights. -->\r\n<!-- Do not remove this test for UTF-8: if “Ω” doesn’t appear as greek uppercase omega letter enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->\r\n<package xmlns=\"http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd\">\r\n  <metadata>\r\n    <!-- == PACKAGE SPECIFIC SECTION == -->\r\n    <!-- This section is about this package, although id and version have ties back to the software -->\r\n    <!-- id is lowercase and if you want a good separator for words, use '-', not '.'. Dots are only acceptable as suffixes for certain types of packages, e.g. .install, .portable, .extension, .template -->\r\n    <!-- If the software is cross-platform, attempt to use the same id as the debian/rpm package(s) if possible. -->\r\n    <id>ffsend</id>\r\n    <!-- version should MATCH as closely as possible with the underlying software -->\r\n    <!-- Is the version a prerelease of a version? https://docs.nuget.org/create/versioning#creating-prerelease-packages -->\r\n    <!-- Note that unstable versions like 0.0.1 can be considered a released version, but it's possible that one can release a 0.0.1-beta before you release a 0.0.1 version. If the version number is final, that is considered a released version and not a prerelease. -->\r\n    <version>0.0.0</version>\r\n    <packageSourceUrl>https://github.com/timvisee/ffsend/tree/master/pkg/choco/ffsend</packageSourceUrl>\r\n    <!-- owners is a poor name for maintainers of the package. It sticks around by this name for compatibility reasons. It basically means you. -->\r\n    <owners>Tim Visee</owners>\r\n    <!-- ============================== -->\r\n\r\n    <!-- == SOFTWARE SPECIFIC SECTION == -->\r\n    <!-- This section is about the software itself -->\r\n    <title>ffsend (Install)</title>\r\n    <authors>Tim Visee</authors>\r\n    <projectUrl>https://github.com/timvisee/ffsend</projectUrl>\r\n    <iconUrl>http://cdn.rawgit.com/timvisee/ffsend/master/res/ffsend.png</iconUrl>\r\n    <copyright>2017-2019 Tim Visee</copyright>\r\n    <licenseUrl>https://raw.githubusercontent.com/timvisee/ffsend/master/LICENSE</licenseUrl>\r\n    <requireLicenseAcceptance>false</requireLicenseAcceptance>\r\n    <projectSourceUrl>https://github.com/timvisee/ffsend</projectSourceUrl>\r\n    <docsUrl>https://github.com/timvisee/ffsend</docsUrl>\r\n    <bugTrackerUrl>https://gitlab.com/timvisee/ffsend/issues</bugTrackerUrl>\r\n    <tags>ffsend firefox-send cli file-sharing file-upload encryption rust</tags>\r\n    <summary>Easily and securely share files from the command line. A fully featured Send client.</summary>\r\n    <description>Easily and securely share files from the command line. A fully featured Send client.</description>\r\n    <!-- =============================== -->      \r\n\r\n    <!-- Specifying dependencies and version ranges? https://docs.nuget.org/create/versioning#specifying-version-ranges-in-.nuspec-files -->\r\n    <dependencies></dependencies>\r\n  </metadata>\r\n  <files>\r\n    <!-- this section controls what actually gets packaged into the Chocolatey package -->\r\n    <file src=\"tools\\**\" target=\"tools\" />\r\n    <!-- Building from Linux? You may need this instead: <file src=\"tools/**\" target=\"tools\" /> -->\r\n  </files>\r\n</package>\r\n"
  },
  {
    "path": "pkg/choco/ffsend/tools/LICENSE.txt",
    "content": "﻿From: https://www.gnu.org/licenses/gpl-3.0.en.html\r\n\r\nLICENSE\r\n\r\n                    GNU GENERAL PUBLIC LICENSE\r\n                       Version 3, 29 June 2007\r\n\r\n Copyright (C) 2018 Tim Visee. <https://timvisee.com/>\r\n Everyone is permitted to copy and distribute verbatim copies\r\n of this license document, but changing it is not allowed.\r\n\r\n                            Preamble\r\n\r\n  The GNU General Public License is a free, copyleft license for\r\nsoftware and other kinds of works.\r\n\r\n  The licenses for most software and other practical works are designed\r\nto take away your freedom to share and change the works.  By contrast,\r\nthe GNU General Public License is intended to guarantee your freedom to\r\nshare and change all versions of a program--to make sure it remains free\r\nsoftware for all its users.  We, the Free Software Foundation, use the\r\nGNU General Public License for most of our software; it applies also to\r\nany other work released this way by its authors.  You can apply it to\r\nyour programs, too.\r\n\r\n  When we speak of free software, we are referring to freedom, not\r\nprice.  Our General Public Licenses are designed to make sure that you\r\nhave the freedom to distribute copies of free software (and charge for\r\nthem if you wish), that you receive source code or can get it if you\r\nwant it, that you can change the software or use pieces of it in new\r\nfree programs, and that you know you can do these things.\r\n\r\n  To protect your rights, we need to prevent others from denying you\r\nthese rights or asking you to surrender the rights.  Therefore, you have\r\ncertain responsibilities if you distribute copies of the software, or if\r\nyou modify it: responsibilities to respect the freedom of others.\r\n\r\n  For example, if you distribute copies of such a program, whether\r\ngratis or for a fee, you must pass on to the recipients the same\r\nfreedoms that you received.  You must make sure that they, too, receive\r\nor can get the source code.  And you must show them these terms so they\r\nknow their rights.\r\n\r\n  Developers that use the GNU GPL protect your rights with two steps:\r\n(1) assert copyright on the software, and (2) offer you this License\r\ngiving you legal permission to copy, distribute and/or modify it.\r\n\r\n  For the developers' and authors' protection, the GPL clearly explains\r\nthat there is no warranty for this free software.  For both users' and\r\nauthors' sake, the GPL requires that modified versions be marked as\r\nchanged, so that their problems will not be attributed erroneously to\r\nauthors of previous versions.\r\n\r\n  Some devices are designed to deny users access to install or run\r\nmodified versions of the software inside them, although the manufacturer\r\ncan do so.  This is fundamentally incompatible with the aim of\r\nprotecting users' freedom to change the software.  The systematic\r\npattern of such abuse occurs in the area of products for individuals to\r\nuse, which is precisely where it is most unacceptable.  Therefore, we\r\nhave designed this version of the GPL to prohibit the practice for those\r\nproducts.  If such problems arise substantially in other domains, we\r\nstand ready to extend this provision to those domains in future versions\r\nof the GPL, as needed to protect the freedom of users.\r\n\r\n  Finally, every program is threatened constantly by software patents.\r\nStates should not allow patents to restrict development and use of\r\nsoftware on general-purpose computers, but in those that do, we wish to\r\navoid the special danger that patents applied to a free program could\r\nmake it effectively proprietary.  To prevent this, the GPL assures that\r\npatents cannot be used to render the program non-free.\r\n\r\n  The precise terms and conditions for copying, distribution and\r\nmodification follow.\r\n\r\n                       TERMS AND CONDITIONS\r\n\r\n  0. Definitions.\r\n\r\n  \"This License\" refers to version 3 of the GNU General Public License.\r\n\r\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\r\nworks, such as semiconductor masks.\r\n\r\n  \"The Program\" refers to any copyrightable work licensed under this\r\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\r\n\"recipients\" may be individuals or organizations.\r\n\r\n  To \"modify\" a work means to copy from or adapt all or part of the work\r\nin a fashion requiring copyright permission, other than the making of an\r\nexact copy.  The resulting work is called a \"modified version\" of the\r\nearlier work or a work \"based on\" the earlier work.\r\n\r\n  A \"covered work\" means either the unmodified Program or a work based\r\non the Program.\r\n\r\n  To \"propagate\" a work means to do anything with it that, without\r\npermission, would make you directly or secondarily liable for\r\ninfringement under applicable copyright law, except executing it on a\r\ncomputer or modifying a private copy.  Propagation includes copying,\r\ndistribution (with or without modification), making available to the\r\npublic, and in some countries other activities as well.\r\n\r\n  To \"convey\" a work means any kind of propagation that enables other\r\nparties to make or receive copies.  Mere interaction with a user through\r\na computer network, with no transfer of a copy, is not conveying.\r\n\r\n  An interactive user interface displays \"Appropriate Legal Notices\"\r\nto the extent that it includes a convenient and prominently visible\r\nfeature that (1) displays an appropriate copyright notice, and (2)\r\ntells the user that there is no warranty for the work (except to the\r\nextent that warranties are provided), that licensees may convey the\r\nwork under this License, and how to view a copy of this License.  If\r\nthe interface presents a list of user commands or options, such as a\r\nmenu, a prominent item in the list meets this criterion.\r\n\r\n  1. Source Code.\r\n\r\n  The \"source code\" for a work means the preferred form of the work\r\nfor making modifications to it.  \"Object code\" means any non-source\r\nform of a work.\r\n\r\n  A \"Standard Interface\" means an interface that either is an official\r\nstandard defined by a recognized standards body, or, in the case of\r\ninterfaces specified for a particular programming language, one that\r\nis widely used among developers working in that language.\r\n\r\n  The \"System Libraries\" of an executable work include anything, other\r\nthan the work as a whole, that (a) is included in the normal form of\r\npackaging a Major Component, but which is not part of that Major\r\nComponent, and (b) serves only to enable use of the work with that\r\nMajor Component, or to implement a Standard Interface for which an\r\nimplementation is available to the public in source code form.  A\r\n\"Major Component\", in this context, means a major essential component\r\n(kernel, window system, and so on) of the specific operating system\r\n(if any) on which the executable work runs, or a compiler used to\r\nproduce the work, or an object code interpreter used to run it.\r\n\r\n  The \"Corresponding Source\" for a work in object code form means all\r\nthe source code needed to generate, install, and (for an executable\r\nwork) run the object code and to modify the work, including scripts to\r\ncontrol those activities.  However, it does not include the work's\r\nSystem Libraries, or general-purpose tools or generally available free\r\nprograms which are used unmodified in performing those activities but\r\nwhich are not part of the work.  For example, Corresponding Source\r\nincludes interface definition files associated with source files for\r\nthe work, and the source code for shared libraries and dynamically\r\nlinked subprograms that the work is specifically designed to require,\r\nsuch as by intimate data communication or control flow between those\r\nsubprograms and other parts of the work.\r\n\r\n  The Corresponding Source need not include anything that users\r\ncan regenerate automatically from other parts of the Corresponding\r\nSource.\r\n\r\n  The Corresponding Source for a work in source code form is that\r\nsame work.\r\n\r\n  2. Basic Permissions.\r\n\r\n  All rights granted under this License are granted for the term of\r\ncopyright on the Program, and are irrevocable provided the stated\r\nconditions are met.  This License explicitly affirms your unlimited\r\npermission to run the unmodified Program.  The output from running a\r\ncovered work is covered by this License only if the output, given its\r\ncontent, constitutes a covered work.  This License acknowledges your\r\nrights of fair use or other equivalent, as provided by copyright law.\r\n\r\n  You may make, run and propagate covered works that you do not\r\nconvey, without conditions so long as your license otherwise remains\r\nin force.  You may convey covered works to others for the sole purpose\r\nof having them make modifications exclusively for you, or provide you\r\nwith facilities for running those works, provided that you comply with\r\nthe terms of this License in conveying all material for which you do\r\nnot control copyright.  Those thus making or running the covered works\r\nfor you must do so exclusively on your behalf, under your direction\r\nand control, on terms that prohibit them from making any copies of\r\nyour copyrighted material outside their relationship with you.\r\n\r\n  Conveying under any other circumstances is permitted solely under\r\nthe conditions stated below.  Sublicensing is not allowed; section 10\r\nmakes it unnecessary.\r\n\r\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\r\n\r\n  No covered work shall be deemed part of an effective technological\r\nmeasure under any applicable law fulfilling obligations under article\r\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\r\nsimilar laws prohibiting or restricting circumvention of such\r\nmeasures.\r\n\r\n  When you convey a covered work, you waive any legal power to forbid\r\ncircumvention of technological measures to the extent such circumvention\r\nis effected by exercising rights under this License with respect to\r\nthe covered work, and you disclaim any intention to limit operation or\r\nmodification of the work as a means of enforcing, against the work's\r\nusers, your or third parties' legal rights to forbid circumvention of\r\ntechnological measures.\r\n\r\n  4. Conveying Verbatim Copies.\r\n\r\n  You may convey verbatim copies of the Program's source code as you\r\nreceive it, in any medium, provided that you conspicuously and\r\nappropriately publish on each copy an appropriate copyright notice;\r\nkeep intact all notices stating that this License and any\r\nnon-permissive terms added in accord with section 7 apply to the code;\r\nkeep intact all notices of the absence of any warranty; and give all\r\nrecipients a copy of this License along with the Program.\r\n\r\n  You may charge any price or no price for each copy that you convey,\r\nand you may offer support or warranty protection for a fee.\r\n\r\n  5. Conveying Modified Source Versions.\r\n\r\n  You may convey a work based on the Program, or the modifications to\r\nproduce it from the Program, in the form of source code under the\r\nterms of section 4, provided that you also meet all of these conditions:\r\n\r\n    a) The work must carry prominent notices stating that you modified\r\n    it, and giving a relevant date.\r\n\r\n    b) The work must carry prominent notices stating that it is\r\n    released under this License and any conditions added under section\r\n    7.  This requirement modifies the requirement in section 4 to\r\n    \"keep intact all notices\".\r\n\r\n    c) You must license the entire work, as a whole, under this\r\n    License to anyone who comes into possession of a copy.  This\r\n    License will therefore apply, along with any applicable section 7\r\n    additional terms, to the whole of the work, and all its parts,\r\n    regardless of how they are packaged.  This License gives no\r\n    permission to license the work in any other way, but it does not\r\n    invalidate such permission if you have separately received it.\r\n\r\n    d) If the work has interactive user interfaces, each must display\r\n    Appropriate Legal Notices; however, if the Program has interactive\r\n    interfaces that do not display Appropriate Legal Notices, your\r\n    work need not make them do so.\r\n\r\n  A compilation of a covered work with other separate and independent\r\nworks, which are not by their nature extensions of the covered work,\r\nand which are not combined with it such as to form a larger program,\r\nin or on a volume of a storage or distribution medium, is called an\r\n\"aggregate\" if the compilation and its resulting copyright are not\r\nused to limit the access or legal rights of the compilation's users\r\nbeyond what the individual works permit.  Inclusion of a covered work\r\nin an aggregate does not cause this License to apply to the other\r\nparts of the aggregate.\r\n\r\n  6. Conveying Non-Source Forms.\r\n\r\n  You may convey a covered work in object code form under the terms\r\nof sections 4 and 5, provided that you also convey the\r\nmachine-readable Corresponding Source under the terms of this License,\r\nin one of these ways:\r\n\r\n    a) Convey the object code in, or embodied in, a physical product\r\n    (including a physical distribution medium), accompanied by the\r\n    Corresponding Source fixed on a durable physical medium\r\n    customarily used for software interchange.\r\n\r\n    b) Convey the object code in, or embodied in, a physical product\r\n    (including a physical distribution medium), accompanied by a\r\n    written offer, valid for at least three years and valid for as\r\n    long as you offer spare parts or customer support for that product\r\n    model, to give anyone who possesses the object code either (1) a\r\n    copy of the Corresponding Source for all the software in the\r\n    product that is covered by this License, on a durable physical\r\n    medium customarily used for software interchange, for a price no\r\n    more than your reasonable cost of physically performing this\r\n    conveying of source, or (2) access to copy the\r\n    Corresponding Source from a network server at no charge.\r\n\r\n    c) Convey individual copies of the object code with a copy of the\r\n    written offer to provide the Corresponding Source.  This\r\n    alternative is allowed only occasionally and noncommercially, and\r\n    only if you received the object code with such an offer, in accord\r\n    with subsection 6b.\r\n\r\n    d) Convey the object code by offering access from a designated\r\n    place (gratis or for a charge), and offer equivalent access to the\r\n    Corresponding Source in the same way through the same place at no\r\n    further charge.  You need not require recipients to copy the\r\n    Corresponding Source along with the object code.  If the place to\r\n    copy the object code is a network server, the Corresponding Source\r\n    may be on a different server (operated by you or a third party)\r\n    that supports equivalent copying facilities, provided you maintain\r\n    clear directions next to the object code saying where to find the\r\n    Corresponding Source.  Regardless of what server hosts the\r\n    Corresponding Source, you remain obligated to ensure that it is\r\n    available for as long as needed to satisfy these requirements.\r\n\r\n    e) Convey the object code using peer-to-peer transmission, provided\r\n    you inform other peers where the object code and Corresponding\r\n    Source of the work are being offered to the general public at no\r\n    charge under subsection 6d.\r\n\r\n  A separable portion of the object code, whose source code is excluded\r\nfrom the Corresponding Source as a System Library, need not be\r\nincluded in conveying the object code work.\r\n\r\n  A \"User Product\" is either (1) a \"consumer product\", which means any\r\ntangible personal property which is normally used for personal, family,\r\nor household purposes, or (2) anything designed or sold for incorporation\r\ninto a dwelling.  In determining whether a product is a consumer product,\r\ndoubtful cases shall be resolved in favor of coverage.  For a particular\r\nproduct received by a particular user, \"normally used\" refers to a\r\ntypical or common use of that class of product, regardless of the status\r\nof the particular user or of the way in which the particular user\r\nactually uses, or expects or is expected to use, the product.  A product\r\nis a consumer product regardless of whether the product has substantial\r\ncommercial, industrial or non-consumer uses, unless such uses represent\r\nthe only significant mode of use of the product.\r\n\r\n  \"Installation Information\" for a User Product means any methods,\r\nprocedures, authorization keys, or other information required to install\r\nand execute modified versions of a covered work in that User Product from\r\na modified version of its Corresponding Source.  The information must\r\nsuffice to ensure that the continued functioning of the modified object\r\ncode is in no case prevented or interfered with solely because\r\nmodification has been made.\r\n\r\n  If you convey an object code work under this section in, or with, or\r\nspecifically for use in, a User Product, and the conveying occurs as\r\npart of a transaction in which the right of possession and use of the\r\nUser Product is transferred to the recipient in perpetuity or for a\r\nfixed term (regardless of how the transaction is characterized), the\r\nCorresponding Source conveyed under this section must be accompanied\r\nby the Installation Information.  But this requirement does not apply\r\nif neither you nor any third party retains the ability to install\r\nmodified object code on the User Product (for example, the work has\r\nbeen installed in ROM).\r\n\r\n  The requirement to provide Installation Information does not include a\r\nrequirement to continue to provide support service, warranty, or updates\r\nfor a work that has been modified or installed by the recipient, or for\r\nthe User Product in which it has been modified or installed.  Access to a\r\nnetwork may be denied when the modification itself materially and\r\nadversely affects the operation of the network or violates the rules and\r\nprotocols for communication across the network.\r\n\r\n  Corresponding Source conveyed, and Installation Information provided,\r\nin accord with this section must be in a format that is publicly\r\ndocumented (and with an implementation available to the public in\r\nsource code form), and must require no special password or key for\r\nunpacking, reading or copying.\r\n\r\n  7. Additional Terms.\r\n\r\n  \"Additional permissions\" are terms that supplement the terms of this\r\nLicense by making exceptions from one or more of its conditions.\r\nAdditional permissions that are applicable to the entire Program shall\r\nbe treated as though they were included in this License, to the extent\r\nthat they are valid under applicable law.  If additional permissions\r\napply only to part of the Program, that part may be used separately\r\nunder those permissions, but the entire Program remains governed by\r\nthis License without regard to the additional permissions.\r\n\r\n  When you convey a copy of a covered work, you may at your option\r\nremove any additional permissions from that copy, or from any part of\r\nit.  (Additional permissions may be written to require their own\r\nremoval in certain cases when you modify the work.)  You may place\r\nadditional permissions on material, added by you to a covered work,\r\nfor which you have or can give appropriate copyright permission.\r\n\r\n  Notwithstanding any other provision of this License, for material you\r\nadd to a covered work, you may (if authorized by the copyright holders of\r\nthat material) supplement the terms of this License with terms:\r\n\r\n    a) Disclaiming warranty or limiting liability differently from the\r\n    terms of sections 15 and 16 of this License; or\r\n\r\n    b) Requiring preservation of specified reasonable legal notices or\r\n    author attributions in that material or in the Appropriate Legal\r\n    Notices displayed by works containing it; or\r\n\r\n    c) Prohibiting misrepresentation of the origin of that material, or\r\n    requiring that modified versions of such material be marked in\r\n    reasonable ways as different from the original version; or\r\n\r\n    d) Limiting the use for publicity purposes of names of licensors or\r\n    authors of the material; or\r\n\r\n    e) Declining to grant rights under trademark law for use of some\r\n    trade names, trademarks, or service marks; or\r\n\r\n    f) Requiring indemnification of licensors and authors of that\r\n    material by anyone who conveys the material (or modified versions of\r\n    it) with contractual assumptions of liability to the recipient, for\r\n    any liability that these contractual assumptions directly impose on\r\n    those licensors and authors.\r\n\r\n  All other non-permissive additional terms are considered \"further\r\nrestrictions\" within the meaning of section 10.  If the Program as you\r\nreceived it, or any part of it, contains a notice stating that it is\r\ngoverned by this License along with a term that is a further\r\nrestriction, you may remove that term.  If a license document contains\r\na further restriction but permits relicensing or conveying under this\r\nLicense, you may add to a covered work material governed by the terms\r\nof that license document, provided that the further restriction does\r\nnot survive such relicensing or conveying.\r\n\r\n  If you add terms to a covered work in accord with this section, you\r\nmust place, in the relevant source files, a statement of the\r\nadditional terms that apply to those files, or a notice indicating\r\nwhere to find the applicable terms.\r\n\r\n  Additional terms, permissive or non-permissive, may be stated in the\r\nform of a separately written license, or stated as exceptions;\r\nthe above requirements apply either way.\r\n\r\n  8. Termination.\r\n\r\n  You may not propagate or modify a covered work except as expressly\r\nprovided under this License.  Any attempt otherwise to propagate or\r\nmodify it is void, and will automatically terminate your rights under\r\nthis License (including any patent licenses granted under the third\r\nparagraph of section 11).\r\n\r\n  However, if you cease all violation of this License, then your\r\nlicense from a particular copyright holder is reinstated (a)\r\nprovisionally, unless and until the copyright holder explicitly and\r\nfinally terminates your license, and (b) permanently, if the copyright\r\nholder fails to notify you of the violation by some reasonable means\r\nprior to 60 days after the cessation.\r\n\r\n  Moreover, your license from a particular copyright holder is\r\nreinstated permanently if the copyright holder notifies you of the\r\nviolation by some reasonable means, this is the first time you have\r\nreceived notice of violation of this License (for any work) from that\r\ncopyright holder, and you cure the violation prior to 30 days after\r\nyour receipt of the notice.\r\n\r\n  Termination of your rights under this section does not terminate the\r\nlicenses of parties who have received copies or rights from you under\r\nthis License.  If your rights have been terminated and not permanently\r\nreinstated, you do not qualify to receive new licenses for the same\r\nmaterial under section 10.\r\n\r\n  9. Acceptance Not Required for Having Copies.\r\n\r\n  You are not required to accept this License in order to receive or\r\nrun a copy of the Program.  Ancillary propagation of a covered work\r\noccurring solely as a consequence of using peer-to-peer transmission\r\nto receive a copy likewise does not require acceptance.  However,\r\nnothing other than this License grants you permission to propagate or\r\nmodify any covered work.  These actions infringe copyright if you do\r\nnot accept this License.  Therefore, by modifying or propagating a\r\ncovered work, you indicate your acceptance of this License to do so.\r\n\r\n  10. Automatic Licensing of Downstream Recipients.\r\n\r\n  Each time you convey a covered work, the recipient automatically\r\nreceives a license from the original licensors, to run, modify and\r\npropagate that work, subject to this License.  You are not responsible\r\nfor enforcing compliance by third parties with this License.\r\n\r\n  An \"entity transaction\" is a transaction transferring control of an\r\norganization, or substantially all assets of one, or subdividing an\r\norganization, or merging organizations.  If propagation of a covered\r\nwork results from an entity transaction, each party to that\r\ntransaction who receives a copy of the work also receives whatever\r\nlicenses to the work the party's predecessor in interest had or could\r\ngive under the previous paragraph, plus a right to possession of the\r\nCorresponding Source of the work from the predecessor in interest, if\r\nthe predecessor has it or can get it with reasonable efforts.\r\n\r\n  You may not impose any further restrictions on the exercise of the\r\nrights granted or affirmed under this License.  For example, you may\r\nnot impose a license fee, royalty, or other charge for exercise of\r\nrights granted under this License, and you may not initiate litigation\r\n(including a cross-claim or counterclaim in a lawsuit) alleging that\r\nany patent claim is infringed by making, using, selling, offering for\r\nsale, or importing the Program or any portion of it.\r\n\r\n  11. Patents.\r\n\r\n  A \"contributor\" is a copyright holder who authorizes use under this\r\nLicense of the Program or a work on which the Program is based.  The\r\nwork thus licensed is called the contributor's \"contributor version\".\r\n\r\n  A contributor's \"essential patent claims\" are all patent claims\r\nowned or controlled by the contributor, whether already acquired or\r\nhereafter acquired, that would be infringed by some manner, permitted\r\nby this License, of making, using, or selling its contributor version,\r\nbut do not include claims that would be infringed only as a\r\nconsequence of further modification of the contributor version.  For\r\npurposes of this definition, \"control\" includes the right to grant\r\npatent sublicenses in a manner consistent with the requirements of\r\nthis License.\r\n\r\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\r\npatent license under the contributor's essential patent claims, to\r\nmake, use, sell, offer for sale, import and otherwise run, modify and\r\npropagate the contents of its contributor version.\r\n\r\n  In the following three paragraphs, a \"patent license\" is any express\r\nagreement or commitment, however denominated, not to enforce a patent\r\n(such as an express permission to practice a patent or covenant not to\r\nsue for patent infringement).  To \"grant\" such a patent license to a\r\nparty means to make such an agreement or commitment not to enforce a\r\npatent against the party.\r\n\r\n  If you convey a covered work, knowingly relying on a patent license,\r\nand the Corresponding Source of the work is not available for anyone\r\nto copy, free of charge and under the terms of this License, through a\r\npublicly available network server or other readily accessible means,\r\nthen you must either (1) cause the Corresponding Source to be so\r\navailable, or (2) arrange to deprive yourself of the benefit of the\r\npatent license for this particular work, or (3) arrange, in a manner\r\nconsistent with the requirements of this License, to extend the patent\r\nlicense to downstream recipients.  \"Knowingly relying\" means you have\r\nactual knowledge that, but for the patent license, your conveying the\r\ncovered work in a country, or your recipient's use of the covered work\r\nin a country, would infringe one or more identifiable patents in that\r\ncountry that you have reason to believe are valid.\r\n\r\n  If, pursuant to or in connection with a single transaction or\r\narrangement, you convey, or propagate by procuring conveyance of, a\r\ncovered work, and grant a patent license to some of the parties\r\nreceiving the covered work authorizing them to use, propagate, modify\r\nor convey a specific copy of the covered work, then the patent license\r\nyou grant is automatically extended to all recipients of the covered\r\nwork and works based on it.\r\n\r\n  A patent license is \"discriminatory\" if it does not include within\r\nthe scope of its coverage, prohibits the exercise of, or is\r\nconditioned on the non-exercise of one or more of the rights that are\r\nspecifically granted under this License.  You may not convey a covered\r\nwork if you are a party to an arrangement with a third party that is\r\nin the business of distributing software, under which you make payment\r\nto the third party based on the extent of your activity of conveying\r\nthe work, and under which the third party grants, to any of the\r\nparties who would receive the covered work from you, a discriminatory\r\npatent license (a) in connection with copies of the covered work\r\nconveyed by you (or copies made from those copies), or (b) primarily\r\nfor and in connection with specific products or compilations that\r\ncontain the covered work, unless you entered into that arrangement,\r\nor that patent license was granted, prior to 28 March 2007.\r\n\r\n  Nothing in this License shall be construed as excluding or limiting\r\nany implied license or other defenses to infringement that may\r\notherwise be available to you under applicable patent law.\r\n\r\n  12. No Surrender of Others' Freedom.\r\n\r\n  If conditions are imposed on you (whether by court order, agreement or\r\notherwise) that contradict the conditions of this License, they do not\r\nexcuse you from the conditions of this License.  If you cannot convey a\r\ncovered work so as to satisfy simultaneously your obligations under this\r\nLicense and any other pertinent obligations, then as a consequence you may\r\nnot convey it at all.  For example, if you agree to terms that obligate you\r\nto collect a royalty for further conveying from those to whom you convey\r\nthe Program, the only way you could satisfy both those terms and this\r\nLicense would be to refrain entirely from conveying the Program.\r\n\r\n  13. Use with the GNU Affero General Public License.\r\n\r\n  Notwithstanding any other provision of this License, you have\r\npermission to link or combine any covered work with a work licensed\r\nunder version 3 of the GNU Affero General Public License into a single\r\ncombined work, and to convey the resulting work.  The terms of this\r\nLicense will continue to apply to the part which is the covered work,\r\nbut the special requirements of the GNU Affero General Public License,\r\nsection 13, concerning interaction through a network will apply to the\r\ncombination as such.\r\n\r\n  14. Revised Versions of this License.\r\n\r\n  The Free Software Foundation may publish revised and/or new versions of\r\nthe GNU General Public License from time to time.  Such new versions will\r\nbe similar in spirit to the present version, but may differ in detail to\r\naddress new problems or concerns.\r\n\r\n  Each version is given a distinguishing version number.  If the\r\nProgram specifies that a certain numbered version of the GNU General\r\nPublic License \"or any later version\" applies to it, you have the\r\noption of following the terms and conditions either of that numbered\r\nversion or of any later version published by the Free Software\r\nFoundation.  If the Program does not specify a version number of the\r\nGNU General Public License, you may choose any version ever published\r\nby the Free Software Foundation.\r\n\r\n  If the Program specifies that a proxy can decide which future\r\nversions of the GNU General Public License can be used, that proxy's\r\npublic statement of acceptance of a version permanently authorizes you\r\nto choose that version for the Program.\r\n\r\n  Later license versions may give you additional or different\r\npermissions.  However, no additional obligations are imposed on any\r\nauthor or copyright holder as a result of your choosing to follow a\r\nlater version.\r\n\r\n  15. Disclaimer of Warranty.\r\n\r\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\r\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\r\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\r\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\r\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\r\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\r\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\r\n\r\n  16. Limitation of Liability.\r\n\r\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\r\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\r\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\r\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\r\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\r\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\r\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\r\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\r\nSUCH DAMAGES.\r\n\r\n  17. Interpretation of Sections 15 and 16.\r\n\r\n  If the disclaimer of warranty and limitation of liability provided\r\nabove cannot be given local legal effect according to their terms,\r\nreviewing courts shall apply local law that most closely approximates\r\nan absolute waiver of all civil liability in connection with the\r\nProgram, unless a warranty or assumption of liability accompanies a\r\ncopy of the Program in return for a fee.\r\n\r\n                     END OF TERMS AND CONDITIONS\r\n\r\n            How to Apply These Terms to Your New Programs\r\n\r\n  If you develop a new program, and you want it to be of the greatest\r\npossible use to the public, the best way to achieve this is to make it\r\nfree software which everyone can redistribute and change under these terms.\r\n\r\n  To do so, attach the following notices to the program.  It is safest\r\nto attach them to the start of each source file to most effectively\r\nstate the exclusion of warranty; and each file should have at least\r\nthe \"copyright\" line and a pointer to where the full notice is found.\r\n\r\n    <one line to give the program's name and a brief idea of what it does.>\r\n    Copyright (C) <year>  <name of author>\r\n\r\n    This program is free software: you can redistribute it and/or modify\r\n    it under the terms of the GNU General Public License as published by\r\n    the Free Software Foundation, either version 3 of the License, or\r\n    (at your option) any later version.\r\n\r\n    This program is distributed in the hope that it will be useful,\r\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n    GNU General Public License for more details.\r\n\r\n    You should have received a copy of the GNU General Public License\r\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\r\n\r\nAlso add information on how to contact you by electronic and paper mail.\r\n\r\n  If the program does terminal interaction, make it output a short\r\nnotice like this when it starts in an interactive mode:\r\n\r\n    <program>  Copyright (C) <year>  <name of author>\r\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\r\n    This is free software, and you are welcome to redistribute it\r\n    under certain conditions; type `show c' for details.\r\n\r\nThe hypothetical commands `show w' and `show c' should show the appropriate\r\nparts of the General Public License.  Of course, your program's commands\r\nmight be different; for a GUI interface, you would use an \"about box\".\r\n\r\n  You should also get your employer (if you work as a programmer) or school,\r\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\r\nFor more information on this, and how to apply and follow the GNU GPL, see\r\n<http://www.gnu.org/licenses/>.\r\n\r\n  The GNU General Public License does not permit incorporating your program\r\ninto proprietary programs.  If your program is a subroutine library, you\r\nmay consider it more useful to permit linking proprietary applications with\r\nthe library.  If this is what you want to do, use the GNU Lesser General\r\nPublic License instead of this License.  But first, please read\r\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\r\n"
  },
  {
    "path": "pkg/choco/ffsend/tools/VERIFICATION.txt",
    "content": "﻿VERIFICATION\r\nVerification is intended to assist the Chocolatey moderators and community\r\nin verifying that this package's contents are trustworthy.\r\n \r\nBinaries can be compared to versions available at: https://github.com/timvisee/ffsend/releases\r\n"
  },
  {
    "path": "pkg/create_deb",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# Ensure the version tag is valid\nif [[ ! $TRAVIS_TAG =~ ^v([0-9]+\\.)*[0-9]+$ ]]; then\n    echo \"Error: invalid Git tag in \\$TRAVIS_TAG, must be in 'v0.0.0' format\"\n    exit 1\nfi\n\n# Ensure the debian architecture is set\nif [[ -z $DEB_ARCH ]]; then\n    echo \"Error: debian architecture not configured in \\$DEB_ARCH\"\n    exit 1\nfi\n\n# Define some useful variables\nDIR=$( cd \"$( dirname \"${BASH_SOURCE[0]}\" )\" && pwd )\nVERSION=${TRAVIS_TAG:1}\n\n# Ensure the binary file exists\nif [[ ! -f \"$DIR/../ffsend\" ]]; then\n    echo \"Error: missing 'ffsend' binary in repository root\"\n    exit 1\nfi\n\n# Create an application directory, copy the binary into it\nmkdir -p \"$DIR/ffsend-$VERSION\"\ncp -- \"$DIR/../ffsend\" \"$DIR/ffsend-$VERSION/ffsend\"\n\n# Create an application tarball\ncd -- \"$DIR/..\"\ngit archive --format tar.gz -o \"$DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz\" \"$TRAVIS_TAG\"\n\n# Change into the app directory\ncd -- \"$DIR/ffsend-$VERSION\"\n\n# Build the debian package\n# TODO: define GPG?\ndh_make -e \"timvisee@gmail.com\" -c gpl3 -f \"ffsend-$VERSION.tar.gz\" -s -y\nrm -- *.ex README.Debian README.source\n\n# Remove the project tar ball, we're not using it anymore\nrm -- \"$DIR/ffsend-$VERSION/ffsend-$VERSION.tar.gz\"\n\n# TODO: configure the debian/control file\n# TODO: configure copyright file\n\n\n\n\n\n# # Update version and architecture in the control file\n# sed -i \"/Version:\\.*/c\\\\Version: $VERSION\" $DIR/deb/DEBIAN/control\n# sed -i \"/Architecture:\\.*/c\\\\Architecture: $DEB_ARCH\" $DIR/deb/DEBIAN/control\n\n# # Build the debian package\n# echo \"Building debian package...\"\n# dpkg-deb --verbose --build $DIR/deb .\n"
  },
  {
    "path": "pkg/deb/postinst",
    "content": "#!/usr/bin/env bash\n\n# Create an ffs alias\nif [[ ! -f /usr/bin/ffs ]]; then\n    echo \"Creating ffs alias for ffsend...\"\n    ln -s /usr/bin/ffsend /usr/bin/ffs\nfi\n"
  },
  {
    "path": "pkg/deb/prerm",
    "content": "#!/usr/bin/env bash\n\n# Unlink the ffs alias if it links to ffsend\nif [[ -L /usr/bin/ffs ]] \\\n    && [[ $(realpath /usr/bin/ffs) == \"/usr/bin/ffsend\" ]]; \\\nthen\n    echo \"Removing ffs alias for ffsend...\"\n    unlink /usr/bin/ffs\nfi\n"
  },
  {
    "path": "pkg/docker/Dockerfile",
    "content": "FROM alpine:latest\nLABEL maintainer=\"Tim Visée <3a4fb3964f@sinenomine.email>\"\n\nCOPY ./ffsend /\n\nWORKDIR /data/\nENTRYPOINT [\"/ffsend\"]\n"
  },
  {
    "path": "pkg/scoop/README.md",
    "content": "# scoop manifest for ffsend\nThis directory contains a [`scoop`][scoop] manifest template for `ffsend`.\n\nThe currently published manifest can be found in the `scoop` repository,\nand is automatically updated:  \nhttps://github.com/ScoopInstaller/Main/blob/master/bucket/ffsend.json\n\n[scoop]: https://scoop.rs/\n"
  },
  {
    "path": "pkg/scoop/ffsend.json",
    "content": "{\n    \"homepage\": \"https://github.com/timvisee/ffsend\",\n    \"description\": \"Easily and securely share files from the command line. A fully featured Send client.\",\n    \"license\": \"GPL-3.0-only\",\n    \"version\": \"0.0.0\",\n    \"architecture\": {\n        \"64bit\": {\n            \"url\": \"https://github.com/timvisee/ffsend/releases/download/v0.2.30/ffsend-v0.2.30-windows-x64-static.exe#/ffsend.exe\",\n            \"hash\": \"297f1405bacdc34948cd94ba785336c48e1ac862984268d66a8928abd3e322e1\"\n        }\n    },\n    \"bin\": \"ffsend.exe\",\n    \"checkver\": \"github\",\n    \"autoupdate\": {\n        \"architecture\": {\n            \"64bit\": {\n                \"url\": \"https://github.com/timvisee/ffsend/releases/download/v$version/ffsend-v$version-windows-x64-static.exe#/ffsend.exe\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "res/asciinema-demo.json",
    "content": "{\n  \"version\": 1,\n  \"width\": 102,\n  \"height\": 19,\n  \"duration\": 78.431135,\n  \"command\": null,\n  \"title\": \"ffsend v0.0.9 demo\",\n  \"env\": {\n    \"TERM\": \"xterm-256color\",\n    \"SHELL\": \"/bin/bash\"\n  },\n  \"stdout\": [\n    [\n      0.000446,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      1,\n      \"f\"\n    ],\n    [\n      0.311074,\n      \"f\"\n    ],\n    [\n      0.107298,\n      \"s\"\n    ],\n    [\n      0.112108,\n      \"e\"\n    ],\n    [\n      0.052915,\n      \"n\"\n    ],\n    [\n      0.103452,\n      \"d\"\n    ],\n    [\n      0.076084,\n      \"\\r\\n\"\n    ],\n    [\n      0.004048,\n      \"ffsend 0.0.7\\r\\nUsage: ffsend [FLAGS] <SUBCOMMAND> ...\\r\\n\\r\\nSecurely and easily share files from the command line.\\r\\nA fully featured Firefox Send client.\\r\\n\\r\\nMissing subcommand. Here are the most used:\\r\\n\"\n    ],\n    [\n      0.000148,\n      \"    \\u001b[33mffsend upload <FILE> ...\\u001b[0m\\r\\n    \\u001b[33mffsend download <URL> ...\\u001b[0m\\r\\n\\r\\nTo show all subcommands, features and other help:\\r\\n    \\u001b[33mffsend help [SUBCOMMAND]\\u001b[0m\\r\\n\"\n    ],\n    [\n      0.000414,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      3.727418,\n      \"\\r\\n\"\n    ],\n    [\n      0.000203,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.097661,\n      \"f\"\n    ],\n    [\n      0.122247,\n      \"f\"\n    ],\n    [\n      0.05605,\n      \"s\"\n    ],\n    [\n      0.087885,\n      \"e\"\n    ],\n    [\n      0.060899,\n      \"n\"\n    ],\n    [\n      0.096174,\n      \"d\"\n    ],\n    [\n      0.061232,\n      \" \"\n    ],\n    [\n      0.060431,\n      \"u\"\n    ],\n    [\n      0.03782,\n      \"p\"\n    ],\n    [\n      0.13847,\n      \"l\"\n    ],\n    [\n      0.11866,\n      \"o\"\n    ],\n    [\n      0.033067,\n      \"a\"\n    ],\n    [\n      0.027852,\n      \"d\"\n    ],\n    [\n      0.069364,\n      \" \"\n    ],\n    [\n      0.084982,\n      \"i\"\n    ],\n    [\n      0.051328,\n      \"m\"\n    ],\n    [\n      0.010214,\n      \"a\"\n    ],\n    [\n      0.054744,\n      \"g\"\n    ],\n    [\n      0.059566,\n      \"e\"\n    ],\n    [\n      0.036545,\n      \".\"\n    ],\n    [\n      0.136904,\n      \"p\"\n    ],\n    [\n      0.144499,\n      \"n\"\n    ],\n    [\n      0.075098,\n      \"g\"\n    ],\n    [\n      0.063966,\n      \" \"\n    ],\n    [\n      0.197218,\n      \"-\"\n    ],\n    [\n      0.098887,\n      \"-\"\n    ],\n    [\n      0.183252,\n      \"c\"\n    ],\n    [\n      0.076421,\n      \"o\"\n    ],\n    [\n      0.055157,\n      \"p\"\n    ],\n    [\n      0.083875,\n      \"y\"\n    ],\n    [\n      1.318772,\n      \"\\r\\n\"\n    ],\n    [\n      0.006129,\n      \"\\rEncrypt & Upload 7.88 KB / 116.93 KB [==>-------------------------------------] 6.74 % 164.29 MB/s 0s \"\n    ],\n    [\n      0.004434,\n      \"\\rEncrypt & Upload 116.93 KB / 116.93 KB [=======================================] 100.00 % 26.44 MB/s  \\rUpload complete\\r\\n\"\n    ],\n    [\n      0.000379,\n      \"Share link:\\u001b(B\\u001b[m  http://send.firefox.com/download/eb2ab818cc/#F8_WgM3tz1t05yiPMsBgIw\\u001b(B\\u001b[m  \\r\\n\"\n    ],\n    [\n      0.010614,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      2.025804,\n      \"\\r\\n\"\n    ],\n    [\n      0.000202,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.243031,\n      \"f\"\n    ],\n    [\n      0.139251,\n      \"f\"\n    ],\n    [\n      0.023956,\n      \"s\"\n    ],\n    [\n      0.147834,\n      \"e\"\n    ],\n    [\n      0.08333,\n      \"n\"\n    ],\n    [\n      0.10299,\n      \"d\"\n    ],\n    [\n      0.060944,\n      \" \"\n    ],\n    [\n      0.101654,\n      \"d\"\n    ],\n    [\n      0.070479,\n      \"o\"\n    ],\n    [\n      0.072873,\n      \"w\"\n    ],\n    [\n      0.074426,\n      \"n\"\n    ],\n    [\n      0.052316,\n      \"l\"\n    ],\n    [\n      0.123539,\n      \"o\"\n    ],\n    [\n      0.050095,\n      \"a\"\n    ],\n    [\n      0.042724,\n      \"d\"\n    ],\n    [\n      0.059361,\n      \" \"\n    ],\n    [\n      0.394567,\n      \"http://send.firefox.com/download/eb2ab818cc/#F8_WgM3tz1t05yiPMsBgIw\"\n    ],\n    [\n      1.808662,\n      \"\\r\\n\"\n    ],\n    [\n      0.018087,\n      \"The path '/home/timvisee/ffsend/image.png' already exists\\r\\nOverwrite? [y/n]: \"\n    ],\n    [\n      2.255111,\n      \"y\"\n    ],\n    [\n      0.344455,\n      \"\\r\\n\"\n    ],\n    [\n      0.006962,\n      \"\\rDownload & Decrypt 7.49 KB / 116.93 KB [==>------------------------------------] 6.41 % 45.45 MB/s 0s \"\n    ],\n    [\n      0.002159,\n      \"\\rDownload & Decrypt 116.93 KB / 116.93 KB [=====================================] 100.00 % 46.05 MB/s  \\rDownload completed\\r\\n\"\n    ],\n    [\n      0.00258,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      1.273051,\n      \"c\"\n    ],\n    [\n      0.085775,\n      \"l\"\n    ],\n    [\n      0.088002,\n      \"e\"\n    ],\n    [\n      0.063911,\n      \"a\"\n    ],\n    [\n      0.028405,\n      \"r\"\n    ],\n    [\n      0.117617,\n      \"\\r\\n\"\n    ],\n    [\n      0.002596,\n      \"\\u001b[3J\\u001b[H\\u001b[2J\"\n    ],\n    [\n      0.000426,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.451685,\n      \"t\"\n    ],\n    [\n      0.147318,\n      \"r\"\n    ],\n    [\n      0.035882,\n      \"e\"\n    ],\n    [\n      0.143284,\n      \"e\"\n    ],\n    [\n      0.099064,\n      \"\\r\\n\"\n    ],\n    [\n      0.001387,\n      \"\\u001b[01;34m.\\u001b[00m\\r\\n\"\n    ],\n    [\n      4.6e-05,\n      \"├── \\u001b[01;34mdir\\u001b[00m\\r\\n\"\n    ],\n    [\n      8.2e-05,\n      \"│   ├── \\u001b[01;35mimage1.png\\u001b[00m\\r\\n│   ├── \\u001b[01;35mimage2.png\\u001b[00m\\r\\n│   ├── \\u001b[01;35mimage3.png\\u001b[00m\\r\\n\"\n    ],\n    [\n      3.5e-05,\n      \"│   ├── \\u001b[01;35mimage4.png\\u001b[00m\\r\\n│   └── \\u001b[01;35mimage5.png\\u001b[00m\\r\\n└── \\u001b[01;35mimage.png\\u001b[00m\\r\\n\\r\\n1 directory, 6 files\\r\\n\"\n    ],\n    [\n      0.000269,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      1.35093,\n      \"f\"\n    ],\n    [\n      0.138635,\n      \"f\"\n    ],\n    [\n      0.027636,\n      \"s\"\n    ],\n    [\n      0.108943,\n      \"e\"\n    ],\n    [\n      0.083283,\n      \"n\"\n    ],\n    [\n      0.081298,\n      \"d\"\n    ],\n    [\n      0.066286,\n      \" \"\n    ],\n    [\n      0.124465,\n      \"u\"\n    ],\n    [\n      0.123613,\n      \"p\"\n    ],\n    [\n      0.198503,\n      \"l\"\n    ],\n    [\n      0.197546,\n      \"o\"\n    ],\n    [\n      0.093234,\n      \"a\"\n    ],\n    [\n      0.039311,\n      \"d\"\n    ],\n    [\n      0.074587,\n      \" \"\n    ],\n    [\n      0.155511,\n      \"-\"\n    ],\n    [\n      0.107025,\n      \"-\"\n    ],\n    [\n      0.30897,\n      \"h\"\n    ],\n    [\n      0.038037,\n      \"o\"\n    ],\n    [\n      0.050418,\n      \"s\"\n    ],\n    [\n      0.065752,\n      \"t\"\n    ],\n    [\n      0.037937,\n      \" \"\n    ],\n    [\n      0.22728,\n      \"h\"\n    ],\n    [\n      0.162005,\n      \"t\"\n    ],\n    [\n      0.129107,\n      \"t\"\n    ],\n    [\n      0.057937,\n      \"p\"\n    ],\n    [\n      0.185544,\n      \":\"\n    ],\n    [\n      0.149125,\n      \"/\"\n    ],\n    [\n      0.105709,\n      \"/\"\n    ],\n    [\n      0.179433,\n      \"l\"\n    ],\n    [\n      0.149999,\n      \"o\"\n    ],\n    [\n      0.054508,\n      \"c\"\n    ],\n    [\n      0.028218,\n      \"a\"\n    ],\n    [\n      0.083596,\n      \"l\"\n    ],\n    [\n      0.166794,\n      \"h\"\n    ],\n    [\n      0.061429,\n      \"o\"\n    ],\n    [\n      0.062438,\n      \"s\"\n    ],\n    [\n      0.048826,\n      \"t\"\n    ],\n    [\n      0.277334,\n      \"/\"\n    ],\n    [\n      0.097705,\n      \" \"\n    ],\n    [\n      0.898511,\n      \".\"\n    ],\n    [\n      0.243449,\n      \"/\"\n    ],\n    [\n      0.13176,\n      \"d\"\n    ],\n    [\n      0.087721,\n      \"i\"\n    ],\n    [\n      0.069036,\n      \"r\"\n    ],\n    [\n      0.056833,\n      \" \"\n    ],\n    [\n      0.423555,\n      \"-\"\n    ],\n    [\n      0.103734,\n      \"-\"\n    ],\n    [\n      0.075639,\n      \"c\"\n    ],\n    [\n      0.079152,\n      \"o\"\n    ],\n    [\n      0.075414,\n      \"p\"\n    ],\n    [\n      0.067769,\n      \"y\"\n    ],\n    [\n      0.048457,\n      \" \"\n    ],\n    [\n      0.139606,\n      \"-\"\n    ],\n    [\n      0.085638,\n      \"-\"\n    ],\n    [\n      0.159108,\n      \"p\"\n    ],\n    [\n      0.057905,\n      \"a\"\n    ],\n    [\n      0.127221,\n      \"s\"\n    ],\n    [\n      0.125608,\n      \"s\"\n    ],\n    [\n      0.151744,\n      \"w\"\n    ],\n    [\n      0.097711,\n      \"o\"\n    ],\n    [\n      0.061007,\n      \"r\"\n    ],\n    [\n      0.154988,\n      \"d\"\n    ],\n    [\n      0.078481,\n      \" \"\n    ],\n    [\n      0.114123,\n      \"-\"\n    ],\n    [\n      0.091159,\n      \"-\"\n    ],\n    [\n      0.070143,\n      \"d\"\n    ],\n    [\n      0.11245,\n      \"o\"\n    ],\n    [\n      0.041233,\n      \"w\"\n    ],\n    [\n      0.135844,\n      \"n\"\n    ],\n    [\n      0.082433,\n      \"l\"\n    ],\n    [\n      0.136912,\n      \"o\"\n    ],\n    [\n      0.045263,\n      \"a\"\n    ],\n    [\n      0.070978,\n      \"d\"\n    ],\n    [\n      0.157074,\n      \"s\"\n    ],\n    [\n      0.0916,\n      \" \"\n    ],\n    [\n      0.139081,\n      \"1\"\n    ],\n    [\n      0.082388,\n      \"0\"\n    ],\n    [\n      0.546882,\n      \"\\r\\n\"\n    ],\n    [\n      0.010193,\n      \"You've selected a directory, only a single file may be uploaded.\\r\\nArchive the directory into a single file? [Y/n]: \"\n    ],\n    [\n      3.589859,\n      \"y\"\n    ],\n    [\n      0.328803,\n      \"\\r\\nArchiving...\\r\\n\"\n    ],\n    [\n      0.001366,\n      \"Password: \"\n    ],\n    [\n      2.049001,\n      \"\\r\\n\"\n    ],\n    [\n      0.0006,\n      \"\\rEncrypt & Upload 7.88 KB / 589.02 KB [>----------------------------------------] 1.34 % 73.23 MB/s 0s \"\n    ],\n    [\n      0.056393,\n      \"\\rEncrypt & Upload 589.02 KB / 589.02 KB [=======================================] 100.00 % 10.18 MB/s  \"\n    ],\n    [\n      0.000241,\n      \"\\rUpload complete\\r\\n\"\n    ],\n    [\n      0.007118,\n      \"Share link:\\u001b(B\\u001b[m  http://localhost/download/8c676a0415/#ppyvURZnNKxAXP503zx4ow\\u001b(B\\u001b[m  \\r\\n\"\n    ],\n    [\n      0.013095,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      2.812126,\n      \"r\"\n    ],\n    [\n      0.106401,\n      \"m\"\n    ],\n    [\n      0.065776,\n      \" \"\n    ],\n    [\n      0.109802,\n      \"-\"\n    ],\n    [\n      0.107358,\n      \"r\"\n    ],\n    [\n      0.052046,\n      \" \"\n    ],\n    [\n      0.197937,\n      \"d\"\n    ],\n    [\n      0.110728,\n      \"i\"\n    ],\n    [\n      0.088048,\n      \"r\"\n    ],\n    [\n      0.478528,\n      \"\\r\\n\"\n    ],\n    [\n      0.001914,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      1.696512,\n      \"t\"\n    ],\n    [\n      0.165512,\n      \"r\"\n    ],\n    [\n      0.053922,\n      \"e\"\n    ],\n    [\n      0.136209,\n      \"e\"\n    ],\n    [\n      0.617314,\n      \"\\r\\n\"\n    ],\n    [\n      0.002698,\n      \"\\u001b[01;34m.\\u001b[00m\\r\\n└── \\u001b[01;35mimage.png\\u001b[00m\\r\\n\\r\\n0 directories, 1 file\\r\\n\"\n    ],\n    [\n      0.000599,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      2.565528,\n      \"\\r\\n\"\n    ],\n    [\n      0.000117,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.101676,\n      \"f\"\n    ],\n    [\n      0.134166,\n      \"f\"\n    ],\n    [\n      0.052074,\n      \"s\"\n    ],\n    [\n      0.113215,\n      \"e\"\n    ],\n    [\n      0.094931,\n      \"n\"\n    ],\n    [\n      0.071806,\n      \"d\"\n    ],\n    [\n      0.067825,\n      \" \"\n    ],\n    [\n      0.074399,\n      \"d\"\n    ],\n    [\n      0.073672,\n      \"o\"\n    ],\n    [\n      0.062621,\n      \"w\"\n    ],\n    [\n      0.086107,\n      \"n\"\n    ],\n    [\n      0.056469,\n      \"l\"\n    ],\n    [\n      0.132919,\n      \"o\"\n    ],\n    [\n      0.070761,\n      \"a\"\n    ],\n    [\n      0.035916,\n      \"d\"\n    ],\n    [\n      0.051305,\n      \" \"\n    ],\n    [\n      0.451896,\n      \"http://localhost/download/8c676a0415/#ppyvURZnNKxAXP503zx4ow\"\n    ],\n    [\n      1.161843,\n      \"\\r\\n\"\n    ],\n    [\n      0.011099,\n      \"This file is protected with a password.\\r\\nPassword: \"\n    ],\n    [\n      2.810903,\n      \"\\r\\n\"\n    ],\n    [\n      0.008816,\n      \"You're downloading an archive, extract it into the selected directory? [Y/n]: \"\n    ],\n    [\n      2.888769,\n      \"y\"\n    ],\n    [\n      0.275081,\n      \"\\r\\n\"\n    ],\n    [\n      0.004008,\n      \"\\rDownload & Decrypt 7.49 KB / 589.02 KB [>--------------------------------------] 1.27 % 33.97 MB/s 0s \"\n    ],\n    [\n      0.005111,\n      \"\\rDownload & Decrypt 589.02 KB / 589.02 KB [====================================] 100.00 % 105.05 MB/s  \\rDownload complete \\r\\n\"\n    ],\n    [\n      0.001558,\n      \"Extracting...\"\n    ],\n    [\n      0.000667,\n      \"\\r\\n\"\n    ],\n    [\n      0.006159,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      2.29007,\n      \"t\"\n    ],\n    [\n      0.170948,\n      \"r\"\n    ],\n    [\n      0.055106,\n      \"e\"\n    ],\n    [\n      0.141162,\n      \"e\"\n    ],\n    [\n      0.313824,\n      \"\\r\\n\"\n    ],\n    [\n      0.002934,\n      \"\\u001b[01;34m.\\u001b[00m\\r\\n\"\n    ],\n    [\n      0.00015,\n      \"├── \\u001b[01;34mdir\\u001b[00m\"\n    ],\n    [\n      9.2e-05,\n      \"\\r\\n\"\n    ],\n    [\n      0.000103,\n      \"│   ├── \\u001b[01;35mimage1.png\\u001b[00m\"\n    ],\n    [\n      6.5e-05,\n      \"\\r\\n\"\n    ],\n    [\n      8.7e-05,\n      \"│   ├── \\u001b[01;35mimage2.png\\u001b[00m\"\n    ],\n    [\n      6e-05,\n      \"\\r\\n\"\n    ],\n    [\n      8.7e-05,\n      \"│   ├── \\u001b[01;35mimage3.png\\u001b[00m\"\n    ],\n    [\n      8.8e-05,\n      \"\\r\\n\"\n    ],\n    [\n      0.000172,\n      \"│   ├── \\u001b[01;35mimage4.png\\u001b[00m\\r\\n│   └── \\u001b[01;35mimage5.png\\u001b[00m\\r\\n\"\n    ],\n    [\n      6e-05,\n      \"└── \\u001b[01;35mimage.png\\u001b[00m\\r\\n\\r\\n1 directory, 6 files\\r\\n\"\n    ],\n    [\n      0.000758,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      3.895998,\n      \"c\"\n    ],\n    [\n      0.286706,\n      \"l\"\n    ],\n    [\n      0.127313,\n      \"e\"\n    ],\n    [\n      0.068267,\n      \"a\"\n    ],\n    [\n      0.019578,\n      \"r\"\n    ],\n    [\n      0.236386,\n      \"\\r\\n\"\n    ],\n    [\n      0.001683,\n      \"\\u001b[3J\\u001b[H\\u001b[2J\"\n    ],\n    [\n      0.000337,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.328594,\n      \"f\"\n    ],\n    [\n      0.123586,\n      \"f\"\n    ],\n    [\n      0.055619,\n      \"s\"\n    ],\n    [\n      0.094709,\n      \"e\"\n    ],\n    [\n      0.069749,\n      \"n\"\n    ],\n    [\n      0.093652,\n      \"d\"\n    ],\n    [\n      0.060866,\n      \" \"\n    ],\n    [\n      0.036796,\n      \"i\"\n    ],\n    [\n      0.04626,\n      \"n\"\n    ],\n    [\n      0.061367,\n      \" \"\n    ],\n    [\n      0.098436,\n      \"f\"\n    ],\n    [\n      0.218131,\n      \"\\b\\u001b[K\"\n    ],\n    [\n      0.094286,\n      \"\\b\\u001b[K\"\n    ],\n    [\n      0.091956,\n      \"f\"\n    ],\n    [\n      0.093555,\n      \"o\"\n    ],\n    [\n      0.060616,\n      \" \"\n    ],\n    [\n      0.424389,\n      \"http://localhost/download/8c676a0415/#ppyvURZnNKxAXP503zx4ow\"\n    ],\n    [\n      0.537385,\n      \"\\r\\n\"\n    ],\n    [\n      0.009675,\n      \"This file is protected with a password.\\r\\nPassword: \"\n    ],\n    [\n      3.343676,\n      \"\\r\\n\"\n    ],\n    [\n      0.014916,\n      \"ID:       \\u001b(B\\u001b[m  8c676a0415\\u001b(B\\u001b[m  \\r\\nName:     \\u001b(B\\u001b[m  dir.tar\\u001b(B\\u001b[m  \\r\\nSize:     \\u001b(B\\u001b[m  589.02 KiB (603152 B)\\u001b(B\\u001b[m  \\r\\nMIME:     \\u001b(B\\u001b[m  application/x-tar\\u001b(B\\u001b[m  \\r\\nDownloads:\\u001b(B\\u001b[m  1 of 10\\u001b(B\\u001b[m  \\r\\nExpiry:   \\u001b(B\\u001b[m  23h59m (86369s)\\u001b(B\\u001b[m  \\r\\n\"\n    ],\n    [\n      0.001792,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      4.928383,\n      \"\\r\\n\"\n    ],\n    [\n      0.000199,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ],\n    [\n      0.117653,\n      \"f\"\n    ],\n    [\n      0.129906,\n      \"f\"\n    ],\n    [\n      0.032962,\n      \"s\"\n    ],\n    [\n      0.113666,\n      \"e\"\n    ],\n    [\n      0.089314,\n      \"n\"\n    ],\n    [\n      0.065384,\n      \"d\"\n    ],\n    [\n      0.065542,\n      \" \"\n    ],\n    [\n      0.065172,\n      \"h\"\n    ],\n    [\n      0.046016,\n      \"i\"\n    ],\n    [\n      0.033428,\n      \"s\"\n    ],\n    [\n      0.062997,\n      \"t\"\n    ],\n    [\n      0.057587,\n      \"o\"\n    ],\n    [\n      0.09366,\n      \"r\"\n    ],\n    [\n      0.155138,\n      \"y\"\n    ],\n    [\n      0.436485,\n      \"\\r\\n\"\n    ],\n    [\n      0.003618,\n      \"#\\u001b(B\\u001b[m  LINK                                                               \\u001b(B\\u001b[m  EXPIRY\\u001b(B\\u001b[m  OWNER TOKEN\\u001b(B\\u001b[m  \\r\\n1\\u001b(B\\u001b[m  http://localhost/download/8c676a0415/#ppyvURZnNKxAXP503zx4ow       \\u001b(B\\u001b[m  23h59m\\u001b(B\\u001b[m  4cfe63017d9eade8a955\\u001b(B\\u001b[m  \\r\\n2\\u001b(B\\u001b[m  http://send.firefox.com/download/eb2ab818cc/#F8_WgM3tz1t05yiPMsBgIw\\u001b(B\\u001b[m  23h58m\\u001b(B\\u001b[m  084577d86526aa999dc6\\u001b(B\\u001b[m  \\r\\n\"\n    ],\n    [\n      0.000651,\n      \"\\u001b[01;34m~/ffsend\\u001b[00m $ \"\n    ]\n  ]\n}\n"
  },
  {
    "path": "res/asciinema-to-svg",
    "content": "#!/usr/bin/env bash\n\n# Ensure svg-term is installed\nif ! [ -x \"$(command -v svg-term)\" ]; then\n    echo \"svg-term is not installed, unable to create SVG, use:\"\n    echo \"sudo npm install -g svg-term-cli\"\n    exit 1\nfi\n\n# Convert into a GIF\necho \"Generating SVG...\"\ncat asciinema-demo.json | svg-term --out demo.svg --window\necho \"Done\"\n"
  },
  {
    "path": "src/action/debug.rs",
    "content": "use chrono::Duration;\nuse clap::ArgMatches;\nuse ffsend_api::config::SEND_DEFAULT_EXPIRE_TIME;\nuse prettytable::{format::FormatBuilder, Cell, Row, Table};\n\nuse crate::client::to_duration;\nuse crate::cmd::matcher::{debug::DebugMatcher, main::MainMatcher, Matcher};\nuse crate::error::ActionError;\n#[cfg(feature = \"clipboard-bin\")]\nuse crate::util::ClipboardType;\nuse crate::util::{api_version_list, features_list, format_bool, format_duration};\n\n/// A file debug action.\npub struct Debug<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Debug<'a> {\n    /// Construct a new debug action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the debug action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_debug = DebugMatcher::with(self.cmd_matches).unwrap();\n\n        // Create a table for all debug information\n        let mut table = Table::new();\n        table.set_format(FormatBuilder::new().padding(0, 2).build());\n\n        // The crate version\n        table.add_row(Row::new(vec![\n            Cell::new(\"Version:\"),\n            Cell::new(crate_version!()),\n        ]));\n\n        // The default host\n        table.add_row(Row::new(vec![\n            Cell::new(\"Host:\"),\n            Cell::new(matcher_debug.host().as_str()),\n        ]));\n\n        // The history file\n        #[cfg(feature = \"history\")]\n        table.add_row(Row::new(vec![\n            Cell::new(\"History file:\"),\n            Cell::new(matcher_main.history().to_str().unwrap_or(\"?\")),\n        ]));\n\n        // The timeouts\n        table.add_row(Row::new(vec![\n            Cell::new(\"Timeout:\"),\n            Cell::new(\n                &to_duration(matcher_main.timeout())\n                    .map(|t| {\n                        format_duration(\n                            Duration::from_std(t).expect(\"failed to convert timeout duration\"),\n                        )\n                    })\n                    .unwrap_or(\"disabled\".into()),\n            ),\n        ]));\n        table.add_row(Row::new(vec![\n            Cell::new(\"Transfer timeout:\"),\n            Cell::new(\n                &to_duration(matcher_main.transfer_timeout())\n                    .map(|t| {\n                        format_duration(\n                            Duration::from_std(t)\n                                .expect(\"failed to convert transfer timeout duration\"),\n                        )\n                    })\n                    .unwrap_or(\"disabled\".into()),\n            ),\n        ]));\n\n        // The default host\n        table.add_row(Row::new(vec![\n            Cell::new(\"Default expiry:\"),\n            Cell::new(&format_duration(Duration::seconds(\n                SEND_DEFAULT_EXPIRE_TIME as i64,\n            ))),\n        ]));\n\n        // Render a list of compiled features\n        table.add_row(Row::new(vec![\n            Cell::new(\"Features:\"),\n            Cell::new(&features_list().join(\", \")),\n        ]));\n\n        // Render a list of compiled features\n        table.add_row(Row::new(vec![\n            Cell::new(\"API support:\"),\n            Cell::new(&api_version_list().join(\", \")),\n        ]));\n\n        // Show used crypto backend\n        table.add_row(Row::new(vec![\n            Cell::new(\"Crypto backend:\"),\n            #[cfg(feature = \"crypto-ring\")]\n            Cell::new(\"ring\"),\n            #[cfg(feature = \"crypto-openssl\")]\n            Cell::new(\"OpenSSL\"),\n        ]));\n\n        // Clipboard information\n        #[cfg(feature = \"clipboard-bin\")]\n        table.add_row(Row::new(vec![\n            Cell::new(\"Clipboard:\"),\n            Cell::new(&format!(\"{}\", ClipboardType::select())),\n        ]));\n\n        // Show whether quiet is used\n        table.add_row(Row::new(vec![\n            Cell::new(\"Quiet:\"),\n            Cell::new(format_bool(matcher_main.quiet())),\n        ]));\n\n        // Show whether verbose is used\n        table.add_row(Row::new(vec![\n            Cell::new(\"Verbose:\"),\n            Cell::new(format_bool(matcher_main.verbose())),\n        ]));\n\n        // Print the debug table\n        table.printstd();\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/action/delete.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::action::delete::{Delete as ApiDelete, Error as DeleteError};\nuse ffsend_api::file::remote_file::{FileParseError, RemoteFile};\n\nuse crate::client::create_config;\nuse crate::cmd::matcher::{delete::DeleteMatcher, main::MainMatcher, Matcher};\nuse crate::error::ActionError;\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::util::{ensure_owner_token, print_success};\n\n/// A file delete action.\npub struct Delete<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Delete<'a> {\n    /// Construct a new delete action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the delete action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_delete = DeleteMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the share link\n        let url = matcher_delete.url();\n\n        // Create client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Parse the remote file based on the share link, derive the owner token from history\n        let mut file = RemoteFile::parse_url(url, matcher_delete.owner())?;\n        #[cfg(feature = \"history\")]\n        history_tool::derive_file_properties(&matcher_main, &mut file);\n\n        // Ensure the owner token is set\n        ensure_owner_token(file.owner_token_mut(), &matcher_main, false);\n\n        // Send the file deletion request\n        let result = ApiDelete::new(&file, None).invoke(&client);\n        if let Err(DeleteError::Expired) = result {\n            // Remove the file from the history manager if it does not exist\n            #[cfg(feature = \"history\")]\n            history_tool::remove(&matcher_main, &file);\n        }\n        result?;\n\n        // Remove the file from the history manager\n        #[cfg(feature = \"history\")]\n        history_tool::remove(&matcher_main, &file);\n\n        // Print a success message\n        print_success(\"File deleted\");\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Failed to parse a share URL, it was invalid.\n    /// This error is not related to a specific action.\n    #[fail(display = \"invalid share link\")]\n    InvalidUrl(#[cause] FileParseError),\n\n    /// Could not delete, the file has expired or did never exist.\n    #[fail(display = \"the file has expired or did never exist\")]\n    Expired,\n\n    /// An error occurred while deleting the remote file.\n    #[fail(display = \"failed to delete the shared file\")]\n    Delete(#[cause] DeleteError),\n}\n\nimpl From<FileParseError> for Error {\n    fn from(err: FileParseError) -> Error {\n        Error::InvalidUrl(err)\n    }\n}\n\nimpl From<DeleteError> for Error {\n    fn from(err: DeleteError) -> Error {\n        match err {\n            DeleteError::Expired => Error::Expired,\n            err => Error::Delete(err),\n        }\n    }\n}\n"
  },
  {
    "path": "src/action/download.rs",
    "content": "use std::env::current_dir;\nuse std::fs::create_dir_all;\n#[cfg(feature = \"archive\")]\nuse std::io::Error as IoError;\nuse std::path::{self, PathBuf};\nuse std::sync::{Arc, Mutex};\n\nuse clap::ArgMatches;\nuse failure::Fail;\nuse ffsend_api::action::download::{Download as ApiDownload, Error as DownloadError};\nuse ffsend_api::action::exists::{Error as ExistsError, Exists as ApiExists};\nuse ffsend_api::action::metadata::{Error as MetadataError, Metadata as ApiMetadata};\nuse ffsend_api::action::version::Error as VersionError;\nuse ffsend_api::file::remote_file::{FileParseError, RemoteFile};\nuse ffsend_api::pipe::ProgressReporter;\n#[cfg(feature = \"archive\")]\nuse tempfile::{Builder as TempBuilder, NamedTempFile};\n\nuse super::select_api_version;\n#[cfg(feature = \"archive\")]\nuse crate::archive::archive::Archive;\nuse crate::client::create_config;\nuse crate::cmd::matcher::{download::DownloadMatcher, main::MainMatcher, Matcher};\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::progress::ProgressBar;\nuse crate::util::{\n    ensure_enough_space, ensure_password, follow_url, print_error, prompt_yes, quit, quit_error,\n    quit_error_msg, ErrorHints,\n};\n\n/// A file download action.\npub struct Download<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Download<'a> {\n    /// Construct a new download action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the download action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), Error> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_download = DownloadMatcher::with(self.cmd_matches).unwrap();\n\n        // Create a regular client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.clone().client(false);\n\n        // Get the share URL, attempt to follow it\n        let url = matcher_download.url();\n        let url = match follow_url(&client, &url) {\n            Ok(url) => url,\n            Err(err) => {\n                print_error(err.context(\"failed to follow share URL, ignoring\").compat());\n                url\n            }\n        };\n\n        // Guess the host\n        let host = matcher_download.guess_host(Some(url.clone()));\n\n        // Determine the API version to use\n        let mut desired_version = matcher_main.api();\n        select_api_version(&client, host, &mut desired_version)?;\n        let api_version = desired_version.version().unwrap();\n\n        // Parse the remote file based on the share URL\n        let file = RemoteFile::parse_url(url, None)?;\n\n        // Get the target file or directory, and the password\n        let target = matcher_download.output();\n        let mut password = matcher_download.password();\n\n        // Check whether the file exists\n        let exists = ApiExists::new(&file).invoke(&client)?;\n        if !exists.exists() {\n            // Remove the file from the history manager if it does not exist\n            #[cfg(feature = \"history\")]\n            history_tool::remove(&matcher_main, &file);\n\n            return Err(Error::Expired);\n        }\n\n        // Ensure a password is set when required\n        ensure_password(\n            &mut password,\n            exists.requires_password(),\n            &matcher_main,\n            false,\n        );\n\n        // Fetch the file metadata\n        let metadata = ApiMetadata::new(&file, password.clone(), false).invoke(&client)?;\n\n        // A temporary archive file, only used when archiving\n        // The temporary file is stored here, to ensure it's lifetime exceeds the upload process\n        #[cfg(feature = \"archive\")]\n        let mut tmp_archive: Option<NamedTempFile> = None;\n\n        // Check whether to extract\n        #[cfg(feature = \"archive\")]\n        let mut extract = matcher_download.extract();\n\n        #[cfg(feature = \"archive\")]\n        {\n            // Ask to extract if downloading an archive\n            if !extract && metadata.metadata().is_archive() {\n                if prompt_yes(\n                    \"You're downloading an archive, extract it into the selected directory?\",\n                    Some(true),\n                    &matcher_main,\n                ) {\n                    extract = true;\n                }\n            }\n        }\n\n        // Prepare the download target and output path to use\n        #[cfg(feature = \"archive\")]\n        let output_dir = !extract;\n        #[cfg(not(feature = \"archive\"))]\n        let output_dir = false;\n        #[allow(unused_mut)]\n        let mut target = Self::prepare_path(\n            &target,\n            metadata.metadata().name(),\n            &matcher_main,\n            output_dir,\n        );\n        #[cfg(feature = \"archive\")]\n        let output_path = target.clone();\n\n        #[cfg(feature = \"archive\")]\n        {\n            // Allocate an archive file, and update the download and target paths\n            if extract {\n                // TODO: select the extension dynamically\n                let archive_extention = \".tar\";\n\n                // Allocate a temporary file to download the archive to\n                tmp_archive = Some(\n                    TempBuilder::new()\n                        .prefix(&format!(\".{}-archive-\", crate_name!()))\n                        .suffix(archive_extention)\n                        .tempfile()\n                        .map_err(ExtractError::TempFile)?,\n                );\n                if let Some(tmp_archive) = &tmp_archive {\n                    target = tmp_archive.path().to_path_buf();\n                }\n            }\n        }\n\n        // Ensure there is enough disk space available when not being forced\n        if !matcher_main.force() {\n            ensure_enough_space(target.parent().unwrap(), metadata.size());\n        }\n\n        // Create a progress bar reporter\n        let progress_bar = Arc::new(Mutex::new(ProgressBar::new_download()));\n        let progress_reader: Arc<Mutex<dyn ProgressReporter>> = progress_bar;\n\n        // Create a transfer client\n        let transfer_client = client_config.client(true);\n\n        // Execute an download action\n        let progress = if !matcher_main.quiet() {\n            Some(progress_reader)\n        } else {\n            None\n        };\n        ApiDownload::new(api_version, &file, target, password, false, Some(metadata))\n            .invoke(&transfer_client, progress)?;\n\n        // Extract the downloaded file if working with an archive\n        #[cfg(feature = \"archive\")]\n        {\n            if extract {\n                eprintln!(\"Extracting...\");\n\n                // Extract the downloaded file\n                Archive::new(tmp_archive.unwrap().into_file())\n                    .extract(output_path)\n                    .map_err(ExtractError::Extract)?;\n            }\n        }\n\n        // Add the file to the history\n        #[cfg(feature = \"history\")]\n        history_tool::add(&matcher_main, file, true);\n\n        // TODO: open the file, or it's location\n        // TODO: copy the file location\n\n        Ok(())\n    }\n\n    /// This methods prepares a full file path to use for the file to\n    /// download, based on the current directory, the original file name,\n    /// and the user input.\n    /// If `file` is set to false, no file name is included and the path\n    /// will point to a directory.\n    ///\n    /// If no file name was given, the original file name is used.\n    ///\n    /// The full path including the name is returned.\n    ///\n    /// This method will check whether a file is overwritten, and whether\n    /// parent directories must be created.\n    ///\n    /// The program will quit with an error message if a problem occurs.\n    fn prepare_path(\n        target: &PathBuf,\n        name_hint: &str,\n        main_matcher: &MainMatcher,\n        file: bool,\n    ) -> PathBuf {\n        // Select the path to use\n        let mut target = Self::select_path(&target, name_hint);\n\n        // Use the parent directory, if we don't want a file\n        if !file {\n            target = target.parent().unwrap().to_path_buf();\n        }\n\n        // Ask to overwrite\n        if file && target.exists() && !main_matcher.force() {\n            eprintln!(\n                \"The path '{}' already exists\",\n                target.to_str().unwrap_or(\"?\"),\n            );\n            if !prompt_yes(\"Overwrite?\", None, main_matcher) {\n                println!(\"Download cancelled\");\n                quit();\n            }\n        }\n\n        {\n            // Get the deepest directory, as we have to ensure it exists\n            let dir = if file {\n                match target.parent() {\n                    Some(parent) => parent,\n                    None => quit_error_msg(\"invalid output file path\", ErrorHints::default()),\n                }\n            } else {\n                &target\n            };\n\n            // Ensure the directory exists\n            if !dir.is_dir() {\n                // Prompt to create them if not forced\n                if !main_matcher.force() {\n                    eprintln!(\n                        \"The directory '{}' doesn't exists\",\n                        dir.to_str().unwrap_or(\"?\"),\n                    );\n                    if !prompt_yes(\"Create it?\", Some(true), main_matcher) {\n                        println!(\"Download cancelled\");\n                        quit();\n                    }\n                }\n\n                // Create the parent directories\n                if let Err(err) = create_dir_all(dir) {\n                    quit_error(\n                        err.context(\"failed to create parent directories for output file\"),\n                        ErrorHints::default(),\n                    );\n                }\n            }\n        }\n\n        target\n    }\n\n    /// This methods prepares a full file path to use for the file to\n    /// download, based on the current directory, the original file name,\n    /// and the user input.\n    ///\n    /// If no file name was given, the original file name is used.\n    ///\n    /// The full path including the file name will be returned.\n    fn select_path(target: &PathBuf, name_hint: &str) -> PathBuf {\n        // If we're already working with a file, canonicalize and return\n        if target.is_file() {\n            match target.canonicalize() {\n                Ok(target) => return target,\n                Err(err) => quit_error(\n                    err.context(\"failed to canonicalize target path\"),\n                    ErrorHints::default(),\n                ),\n            }\n        }\n\n        // Append the name hint if this is a directory, canonicalize and return\n        if target.is_dir() {\n            match target.canonicalize() {\n                Ok(target) => return target.join(name_hint),\n                Err(err) => quit_error(\n                    err.context(\"failed to canonicalize target path\"),\n                    ErrorHints::default(),\n                ),\n            }\n        }\n\n        // TODO: canonicalize parent if it exists\n\n        // Get the path string\n        let path = target.to_str();\n\n        // If the path is empty, use the working directory with the name hint\n        let use_workdir = path.map(|path| path.trim().is_empty()).unwrap_or(true);\n        if use_workdir {\n            match current_dir() {\n                Ok(target) => return target.join(name_hint),\n                Err(err) => quit_error(\n                    err.context(\"failed to determine working directory to use for the output file\"),\n                    ErrorHints::default(),\n                ),\n            }\n        }\n        let path = path.unwrap();\n\n        // Make the target mutable\n        let mut target = target.clone();\n\n        // If the path ends with a separator, append the name hint\n        if path.trim().ends_with(path::is_separator) {\n            target = target.join(name_hint);\n        }\n\n        // If relative, use the working directory as base\n        if target.is_relative() {\n            match current_dir() {\n                Ok(workdir) => target = workdir.join(target),\n                Err(err) => quit_error(\n                    err.context(\"failed to determine working directory to use for the output file\"),\n                    ErrorHints::default(),\n                ),\n            }\n        }\n\n        target\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Selecting the API version to use failed.\n    // TODO: enable `api` hint!\n    #[fail(display = \"failed to select API version to use\")]\n    Version(#[cause] VersionError),\n\n    /// Failed to parse a share URL, it was invalid.\n    /// This error is not related to a specific action.\n    #[fail(display = \"invalid share link\")]\n    InvalidUrl(#[cause] FileParseError),\n\n    /// An error occurred while checking if the file exists.\n    #[fail(display = \"failed to check whether the file exists\")]\n    Exists(#[cause] ExistsError),\n\n    /// An error occurred while fetching metadata.\n    #[fail(display = \"failed to fetch file metadata\")]\n    Metadata(#[cause] MetadataError),\n\n    /// An error occurred while downloading the file.\n    #[fail(display = \"\")]\n    Download(#[cause] DownloadError),\n\n    /// An error occurred while extracting the file.\n    #[cfg(feature = \"archive\")]\n    #[fail(display = \"failed the extraction procedure\")]\n    Extract(#[cause] ExtractError),\n\n    /// The given Send file has expired, or did never exist in the first place.\n    #[fail(display = \"the file has expired or did never exist\")]\n    Expired,\n}\n\nimpl From<VersionError> for Error {\n    fn from(err: VersionError) -> Error {\n        Error::Version(err)\n    }\n}\n\nimpl From<FileParseError> for Error {\n    fn from(err: FileParseError) -> Error {\n        Error::InvalidUrl(err)\n    }\n}\n\nimpl From<ExistsError> for Error {\n    fn from(err: ExistsError) -> Error {\n        Error::Exists(err)\n    }\n}\n\nimpl From<MetadataError> for Error {\n    fn from(err: MetadataError) -> Error {\n        Error::Metadata(err)\n    }\n}\n\nimpl From<DownloadError> for Error {\n    fn from(err: DownloadError) -> Error {\n        Error::Download(err)\n    }\n}\n\n#[cfg(feature = \"archive\")]\nimpl From<ExtractError> for Error {\n    fn from(err: ExtractError) -> Error {\n        Error::Extract(err)\n    }\n}\n\n#[cfg(feature = \"archive\")]\n#[derive(Debug, Fail)]\npub enum ExtractError {\n    /// An error occurred while creating the temporary archive file.\n    #[fail(display = \"failed to create temporary archive file\")]\n    TempFile(#[cause] IoError),\n\n    /// Failed to extract the file contents to the target directory.\n    #[fail(display = \"failed to extract archive contents to target directory\")]\n    Extract(#[cause] IoError),\n}\n"
  },
  {
    "path": "src/action/exists.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::action::exists::{Error as ExistsError, Exists as ApiExists};\nuse ffsend_api::file::remote_file::{FileParseError, RemoteFile};\n\nuse crate::client::create_config;\nuse crate::cmd::matcher::main::MainMatcher;\nuse crate::cmd::matcher::{exists::ExistsMatcher, Matcher};\nuse crate::error::ActionError;\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\n\n/// A file exists action.\npub struct Exists<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Exists<'a> {\n    /// Construct a new exists action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the exists action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_exists = ExistsMatcher::with(self.cmd_matches).unwrap();\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the share URL\n        let url = matcher_exists.url();\n\n        // Create a reqwest client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Parse the remote file based on the share URL\n        let file = RemoteFile::parse_url(url, None)?;\n\n        // Make sure the file exists\n        let exists_response = ApiExists::new(&file).invoke(&client)?;\n        let exists = exists_response.exists();\n\n        // Print the results\n        println!(\"Exists: {:?}\", exists);\n        if exists {\n            println!(\"Password: {:?}\", exists_response.requires_password());\n        }\n\n        // Add or remove the file from the history\n        #[cfg(feature = \"history\")]\n        {\n            if exists {\n                history_tool::add(&matcher_main, file, false);\n            } else {\n                history_tool::remove(&matcher_main, &file);\n            }\n        }\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Failed to parse a share URL, it was invalid.\n    /// This error is not related to a specific action.\n    #[fail(display = \"invalid share link\")]\n    InvalidUrl(#[cause] FileParseError),\n\n    /// An error occurred while checking if the file exists.\n    #[fail(display = \"failed to check whether the file exists\")]\n    Exists(#[cause] ExistsError),\n}\n\nimpl From<FileParseError> for Error {\n    fn from(err: FileParseError) -> Error {\n        Error::InvalidUrl(err)\n    }\n}\n\nimpl From<ExistsError> for Error {\n    fn from(err: ExistsError) -> Error {\n        Error::Exists(err)\n    }\n}\n"
  },
  {
    "path": "src/action/generate/completions.rs",
    "content": "use std::fs;\nuse std::io;\n\nuse clap::ArgMatches;\n\nuse crate::cmd::matcher::{generate::completions::CompletionsMatcher, main::MainMatcher, Matcher};\nuse crate::error::ActionError;\n\n/// A file completions action.\npub struct Completions<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Completions<'a> {\n    /// Construct a new completions action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the completions action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_completions = CompletionsMatcher::with(self.cmd_matches).unwrap();\n\n        // Obtain shells to generate completions for, build application definition\n        let shells = matcher_completions.shells();\n        let dir = matcher_completions.output();\n        let quiet = matcher_main.quiet();\n        let mut app = crate::cmd::handler::Handler::build();\n\n        // If the directory does not exist yet, attempt to create it\n        if !dir.is_dir() {\n            fs::create_dir_all(&dir).map_err(Error::CreateOutputDir)?;\n        }\n\n        // Generate completions\n        for shell in shells {\n            if !quiet {\n                eprint!(\n                    \"Generating completions for {}...\",\n                    format!(\"{}\", shell).to_lowercase()\n                );\n            }\n            app.gen_completions(crate_name!(), shell, &dir);\n            if !quiet {\n                eprintln!(\" done.\");\n            }\n        }\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// An error occurred while creating the output directory.\n    #[fail(display = \"failed to create output directory, it doesn't exist\")]\n    CreateOutputDir(#[cause] io::Error),\n}\n"
  },
  {
    "path": "src/action/generate/mod.rs",
    "content": "pub mod completions;\n\nuse clap::ArgMatches;\n\nuse crate::cmd::matcher::{generate::GenerateMatcher, Matcher};\nuse crate::error::ActionError;\nuse completions::Completions;\n\n/// A file generate action.\npub struct Generate<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Generate<'a> {\n    /// Construct a new generate action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the generate action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matcher\n        let matcher_generate = GenerateMatcher::with(self.cmd_matches).unwrap();\n\n        // Match shell completions\n        if matcher_generate.matcher_completions().is_some() {\n            return Completions::new(self.cmd_matches).invoke();\n        }\n\n        // Unreachable, clap will print help for missing sub command instead\n        unreachable!()\n    }\n}\n"
  },
  {
    "path": "src/action/history.rs",
    "content": "use clap::ArgMatches;\nuse failure::Fail;\nuse prettytable::{format::FormatBuilder, Cell, Row, Table};\n\nuse crate::cmd::matcher::{history::HistoryMatcher, main::MainMatcher, Matcher};\nuse crate::error::ActionError;\nuse crate::history::{History as HistoryManager, LoadError as HistoryLoadError};\nuse crate::util::{format_duration, quit_error, quit_error_msg, ErrorHintsBuilder};\n\n/// A history action.\npub struct History<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> History<'a> {\n    /// Construct a new history action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the history action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_history = HistoryMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the history path, make sure it exists\n        let history_path = matcher_main.history();\n        if !history_path.is_file() {\n            if !matcher_main.quiet() {\n                eprintln!(\"No files in history\");\n            }\n            return Ok(());\n        }\n\n        // History\n        let mut history = HistoryManager::load(history_path)?;\n\n        // Do not report any files if there aren't any\n        if history.files().is_empty() {\n            if !matcher_main.quiet() {\n                eprintln!(\"No files in history\");\n            }\n            return Ok(());\n        }\n\n        // Clear all history\n        if matcher_history.clear() {\n            history.clear();\n\n            // Save history\n            if let Err(err) = history.save() {\n                quit_error(\n                    err,\n                    ErrorHintsBuilder::default().verbose(true).build().unwrap(),\n                );\n            }\n\n            eprintln!(\"History cleared\");\n            return Ok(());\n        }\n\n        // Remove history item\n        if let Some(url) = matcher_history.rm() {\n            // Remove item, print error if no item with URL was found\n            match history.remove_url(url) {\n                Ok(removed) if !removed => quit_error_msg(\n                    \"could not remove item from history, no item matches given URL\",\n                    ErrorHintsBuilder::default().verbose(true).build().unwrap(),\n                ),\n                Err(err) => quit_error(\n                    err.context(\"could not remove item from history\"),\n                    ErrorHintsBuilder::default().verbose(true).build().unwrap(),\n                ),\n                _ => {}\n            }\n\n            // Save history\n            if let Err(err) = history.save() {\n                quit_error(\n                    err,\n                    ErrorHintsBuilder::default().verbose(true).build().unwrap(),\n                );\n            }\n\n            eprintln!(\"Item removed from history\");\n            return Ok(());\n        }\n\n        // Get the list of files, and sort the first expiring files to be last\n        let mut files = history.files().clone();\n        files.sort_by(|a, b| b.expire_at().cmp(&a.expire_at()));\n\n        // Log a history table, or just the URLs in quiet mode\n        if !matcher_main.quiet() {\n            // Build the list of column names\n            let mut columns = vec![\"#\", \"LINK\", \"EXPIRE\"];\n            if matcher_main.verbose() {\n                columns.push(\"OWNER TOKEN\");\n            }\n\n            // Create a new table\n            let mut table = Table::new();\n            table.set_format(FormatBuilder::new().padding(0, 2).build());\n            table.add_row(Row::new(columns.into_iter().map(Cell::new).collect()));\n\n            // Add an entry for each file\n            for (i, file) in files.iter().enumerate() {\n                // Build the expiry time string\n                let mut expiry = format_duration(&file.expire_duration());\n                if file.expire_uncertain() {\n                    expiry.insert(0, '~');\n                }\n\n                // Get the owner token\n                let owner_token: String = match file.owner_token() {\n                    Some(token) => token.clone(),\n                    None => \"?\".into(),\n                };\n\n                // Define the cell values\n                let mut cells: Vec<String> =\n                    vec![format!(\"{}\", i + 1), file.download_url(true).into(), expiry];\n                if matcher_main.verbose() {\n                    cells.push(owner_token);\n                }\n\n                // Add the row\n                table.add_row(Row::new(cells.into_iter().map(|c| Cell::new(&c)).collect()));\n            }\n\n            // Print the table\n            table.printstd();\n        } else {\n            files\n                .iter()\n                .for_each(|f| println!(\"{}\", f.download_url(true)));\n        }\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Failed to load the history.\n    #[fail(display = \"Failed to load file history\")]\n    Load(#[cause] HistoryLoadError),\n}\n\nimpl From<HistoryLoadError> for ActionError {\n    fn from(err: HistoryLoadError) -> ActionError {\n        ActionError::History(Error::Load(err))\n    }\n}\n"
  },
  {
    "path": "src/action/info.rs",
    "content": "use chrono::Duration;\nuse clap::ArgMatches;\nuse failure::Fail;\nuse ffsend_api::action::exists::{Error as ExistsError, Exists as ApiExists};\nuse ffsend_api::action::info::{Error as InfoError, Info as ApiInfo};\nuse ffsend_api::action::metadata::Metadata as ApiMetadata;\nuse ffsend_api::file::remote_file::{FileParseError, RemoteFile};\nuse prettytable::{format::FormatBuilder, Cell, Row, Table};\n\nuse crate::client::create_config;\nuse crate::cmd::matcher::{info::InfoMatcher, main::MainMatcher, Matcher};\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::util::{\n    ensure_owner_token, ensure_password, format_bytes, format_duration, print_error,\n};\n\n/// A file info action.\npub struct Info<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Info<'a> {\n    /// Construct a new info action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the info action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), Error> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_info = InfoMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the share URL\n        let url = matcher_info.url();\n\n        // Create a reqwest client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Parse the remote file based on the share URL, derive the owner token from history\n        let mut file = RemoteFile::parse_url(url, matcher_info.owner())?;\n        #[cfg(feature = \"history\")]\n        history_tool::derive_file_properties(&matcher_main, &mut file);\n\n        // Ask the user to set the owner token for more detailed information\n        let has_owner = ensure_owner_token(file.owner_token_mut(), &matcher_main, true);\n\n        // Check whether the file exists\n        let exists = ApiExists::new(&file).invoke(&client)?;\n        if !exists.exists() {\n            // Remove the file from the history manager if it doesn't exist\n            #[cfg(feature = \"history\")]\n            history_tool::remove(&matcher_main, &file);\n\n            return Err(Error::Expired);\n        }\n\n        // Get the password, ensure the password is set when required\n        let mut password = matcher_info.password();\n        let has_password = ensure_password(\n            &mut password,\n            exists.requires_password(),\n            &matcher_main,\n            true,\n        );\n\n        // Fetch both file info and metadata\n        let info = if has_owner {\n            Some(ApiInfo::new(&file, None).invoke(&client)?)\n        } else {\n            None\n        };\n        let metadata = if has_password {\n            ApiMetadata::new(&file, password, false)\n                .invoke(&client)\n                .map_err(|err| {\n                    print_error(err.context(\"failed to fetch file metadata, showing limited info\"))\n                })\n                .ok()\n        } else {\n            None\n        };\n\n        // Update history file TTL if info is known\n        if let Some(info) = &info {\n            let ttl_millis = info.ttl_millis() as i64;\n            let ttl = Duration::milliseconds(ttl_millis);\n            file.set_expire_duration(ttl);\n        }\n\n        // Add the file to the history\n        #[cfg(feature = \"history\")]\n        history_tool::add(&matcher_main, file.clone(), true);\n\n        // Create a new table for the information\n        let mut table = Table::new();\n        table.set_format(FormatBuilder::new().padding(0, 2).build());\n\n        // Add the ID\n        table.add_row(Row::new(vec![Cell::new(\"ID:\"), Cell::new(file.id())]));\n\n        // Show file metadata if available\n        if let Some(metadata) = &metadata {\n            // The file name\n            table.add_row(Row::new(vec![\n                Cell::new(\"Name:\"),\n                Cell::new(metadata.metadata().name()),\n            ]));\n\n            // The file size\n            let size = metadata.size();\n            table.add_row(Row::new(vec![\n                Cell::new(\"Size:\"),\n                Cell::new(&if size >= 1024 {\n                    format!(\"{} ({} B)\", format_bytes(size), size)\n                } else {\n                    format_bytes(size)\n                }),\n            ]));\n\n            // The file MIME\n            table.add_row(Row::new(vec![\n                Cell::new(\"MIME:\"),\n                Cell::new(metadata.metadata().mime()),\n            ]));\n        }\n\n        // Show file info if available\n        if let Some(info) = &info {\n            // The download count\n            table.add_row(Row::new(vec![\n                Cell::new(\"Downloads:\"),\n                Cell::new(&format!(\n                    \"{} of {}\",\n                    info.download_count(),\n                    info.download_limit()\n                )),\n            ]));\n\n            // The time to live\n            let ttl_millis = info.ttl_millis() as i64;\n            let ttl = Duration::milliseconds(ttl_millis);\n            table.add_row(Row::new(vec![\n                Cell::new(\"Expiry:\"),\n                Cell::new(&if ttl_millis >= 60 * 1000 {\n                    format!(\"{} ({}s)\", format_duration(&ttl), ttl.num_seconds())\n                } else {\n                    format_duration(&ttl)\n                }),\n            ]));\n        }\n\n        // Print the info table\n        table.printstd();\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Failed to parse a share URL, it was invalid.\n    /// This error is not related to a specific action.\n    #[fail(display = \"invalid share link\")]\n    InvalidUrl(#[cause] FileParseError),\n\n    /// An error occurred while checking if the file exists.\n    #[fail(display = \"failed to check whether the file exists\")]\n    Exists(#[cause] ExistsError),\n\n    /// An error occurred while fetching the file information.\n    #[fail(display = \"failed to fetch file info\")]\n    Info(#[cause] InfoError),\n\n    /// The given Send file has expired, or did never exist in the first place.\n    #[fail(display = \"the file has expired or did never exist\")]\n    Expired,\n}\n\nimpl From<FileParseError> for Error {\n    fn from(err: FileParseError) -> Error {\n        Error::InvalidUrl(err)\n    }\n}\n\nimpl From<ExistsError> for Error {\n    fn from(err: ExistsError) -> Error {\n        Error::Exists(err)\n    }\n}\n\nimpl From<InfoError> for Error {\n    fn from(err: InfoError) -> Error {\n        Error::Info(err)\n    }\n}\n"
  },
  {
    "path": "src/action/mod.rs",
    "content": "pub mod debug;\npub mod delete;\npub mod download;\npub mod exists;\npub mod generate;\n#[cfg(feature = \"history\")]\npub mod history;\npub mod info;\npub mod params;\npub mod password;\npub mod upload;\npub mod version;\n\nuse ffsend_api::action::version::{Error as VersionError, Version as ApiVersion};\nuse ffsend_api::api::DesiredVersion;\nuse ffsend_api::client::Client;\nuse ffsend_api::url::Url;\n\nuse crate::config::API_VERSION_ASSUME;\nuse crate::util::print_warning;\n\n/// Based on the given desired API version, select a version we can use.\n///\n/// If the current desired version is set to the `DesiredVersion::Lookup` variant, this method\n/// will look up the server API version. It it's `DesiredVersion::Use` it will return and\n/// attempt to use the specified version.\nfn select_api_version(\n    client: &Client,\n    host: Url,\n    desired: &mut DesiredVersion,\n) -> Result<(), VersionError> {\n    // Break if already specified\n    if let DesiredVersion::Use(_) = desired {\n        return Ok(());\n    }\n\n    // TODO: only lookup if `DesiredVersion::Assume` after first operation attempt failed\n\n    // Look up the version\n    match ApiVersion::new(host).invoke(&client) {\n        // Use the probed version\n        Ok(v) => *desired = DesiredVersion::Use(v),\n\n        // If unknown, just assume the default version\n        Err(VersionError::Unknown) => {\n            *desired = DesiredVersion::Use(API_VERSION_ASSUME);\n            print_warning(format!(\n                \"server API version could not be determined, assuming v{}\",\n                API_VERSION_ASSUME,\n            ));\n        }\n\n        // Propagate other errors\n        Err(e) => return Err(e),\n    }\n\n    Ok(())\n}\n"
  },
  {
    "path": "src/action/params.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::action::params::{Error as ParamsError, Params as ApiParams, ParamsDataBuilder};\nuse ffsend_api::file::remote_file::RemoteFile;\n\nuse super::select_api_version;\nuse crate::client::create_config;\nuse crate::cmd::matcher::{main::MainMatcher, params::ParamsMatcher, Matcher};\nuse crate::error::ActionError;\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::util::{ensure_owner_token, print_success};\n\n/// A file parameters action.\npub struct Params<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Params<'a> {\n    /// Construct a new parameters action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the parameters action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_params = ParamsMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the share URL and the host\n        // TODO: derive host through helper function\n        let url = matcher_params.url();\n        let mut host = url.clone();\n        host.set_path(\"\");\n        host.set_query(None);\n        host.set_fragment(None);\n\n        // Create a reqwest client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Determine the API version to use\n        let mut desired_version = matcher_main.api();\n        select_api_version(&client, host, &mut desired_version)?;\n        let api_version = desired_version.version().unwrap();\n\n        // Parse the remote file based on the share URL, derive the owner token from history\n        let mut file = RemoteFile::parse_url(url, matcher_params.owner())?;\n        #[cfg(feature = \"history\")]\n        history_tool::derive_file_properties(&matcher_main, &mut file);\n\n        // Ensure the owner token is set\n        ensure_owner_token(file.owner_token_mut(), &matcher_main, false);\n\n        // We don't authenticate for now\n        let auth = false;\n\n        // Build the parameters data object\n        let data = ParamsDataBuilder::default()\n            .download_limit(\n                matcher_params\n                    .download_limit(&matcher_main, api_version, auth)\n                    .map(|d| d as u8),\n            )\n            .build()\n            .unwrap();\n\n        // TODO: make sure the data isn't empty\n\n        // Execute an password action\n        let result = ApiParams::new(&file, data, None).invoke(&client);\n        if let Err(ParamsError::Expired) = result {\n            // Remove the file from the history if expired\n            #[cfg(feature = \"history\")]\n            history_tool::remove(&matcher_main, &file);\n        }\n        result?;\n\n        // Update the history\n        #[cfg(feature = \"history\")]\n        history_tool::add(&matcher_main, file, true);\n\n        // Print a success message\n        print_success(\"Parameters set\");\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/action/password.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::action::password::{Error as PasswordError, Password as ApiPassword};\nuse ffsend_api::file::remote_file::RemoteFile;\nuse prettytable::{format::FormatBuilder, Cell, Row, Table};\n\nuse crate::client::create_config;\nuse crate::cmd::matcher::{main::MainMatcher, password::PasswordMatcher, Matcher};\nuse crate::error::ActionError;\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::util::{ensure_owner_token, print_success};\n\n/// A file password action.\npub struct Password<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Password<'a> {\n    /// Construct a new password action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the password action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_password = PasswordMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the share URL\n        let url = matcher_password.url();\n\n        // Create a reqwest client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Parse the remote file based on the share URL, derive the owner token from history\n        let mut file = RemoteFile::parse_url(url, matcher_password.owner())?;\n        #[cfg(feature = \"history\")]\n        history_tool::derive_file_properties(&matcher_main, &mut file);\n\n        // Ensure the owner token is set\n        ensure_owner_token(file.owner_token_mut(), &matcher_main, false);\n\n        // Get the password to use and whether it was generated\n        let (password, password_generated) = matcher_password.password();\n\n        // Execute an password action\n        let result = ApiPassword::new(&file, &password, None).invoke(&client);\n        if let Err(PasswordError::Expired) = result {\n            // Remove the file from the history if expired\n            #[cfg(feature = \"history\")]\n            history_tool::remove(&matcher_main, &file);\n        }\n        result?;\n\n        // Add the file to the history\n        #[cfg(feature = \"history\")]\n        history_tool::add(&matcher_main, file, true);\n\n        // Print the passphrase if one was generated\n        if password_generated {\n            let mut table = Table::new();\n            table.set_format(FormatBuilder::new().padding(0, 2).build());\n            table.add_row(Row::new(vec![\n                Cell::new(\"Passphrase:\"),\n                Cell::new(&password),\n            ]));\n            table.printstd();\n        }\n\n        // Print a success message\n        print_success(\"Password set\");\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "src/action/upload.rs",
    "content": "use std::env::current_dir;\nuse std::fs;\nuse std::io::{Error as IoError, Write};\nuse std::path::Path;\n#[cfg(feature = \"archive\")]\nuse std::path::PathBuf;\n#[cfg(feature = \"archive\")]\nuse std::process::exit;\nuse std::sync::{Arc, Mutex};\n\nuse clap::ArgMatches;\nuse failure::Fail;\nuse ffsend_api::action::params::ParamsDataBuilder;\nuse ffsend_api::action::upload::{Error as UploadError, Upload as ApiUpload};\nuse ffsend_api::action::version::Error as VersionError;\nuse ffsend_api::config::{upload_size_max, UPLOAD_SIZE_MAX_RECOMMENDED};\nuse ffsend_api::pipe::ProgressReporter;\nuse pathdiff::diff_paths;\nuse prettytable::{format::FormatBuilder, Cell, Row, Table};\n#[cfg(feature = \"qrcode\")]\nuse qr2term::print_qr;\nuse tempfile::{Builder as TempBuilder, NamedTempFile};\n\nuse super::select_api_version;\n#[cfg(feature = \"archive\")]\nuse crate::archive::archiver::Archiver;\nuse crate::client::create_config;\nuse crate::cmd::matcher::{MainMatcher, Matcher, UploadMatcher};\n#[cfg(feature = \"history\")]\nuse crate::history_tool;\nuse crate::progress::ProgressBar;\n#[cfg(feature = \"urlshorten\")]\nuse crate::urlshorten;\n#[cfg(feature = \"clipboard\")]\nuse crate::util::set_clipboard;\nuse crate::util::{\n    format_bytes, open_url, print_error, print_error_msg, prompt_yes, quit, quit_error_msg,\n    rand_alphanum_string, stdin_read_file, ErrorHintsBuilder, StdinErr,\n};\n\n/// A file upload action.\npub struct Upload<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Upload<'a> {\n    /// Construct a new upload action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the upload action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), Error> {\n        // Create the command matchers\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n        let matcher_upload = UploadMatcher::with(self.cmd_matches).unwrap();\n\n        // The file name to use\n        #[allow(unused_mut)]\n        let mut file_name = matcher_upload.name().map(|s| s.to_owned());\n\n        // The selected files\n        let mut files = matcher_upload.files();\n\n        // If file is `-`, upload from stdin\n        // TODO: write stdin directly to file, or directly to upload buffer\n        let mut tmp_stdin: Option<NamedTempFile> = None;\n        if files.len() == 1 && files[0] == \"-\" {\n            // Obtain data from stdin\n            let data = stdin_read_file(!matcher_main.quiet()).map_err(Error::Stdin)?;\n\n            // Create temporary stdin buffer file\n            tmp_stdin = Some(\n                TempBuilder::new()\n                    .prefix(&format!(\".{}-stdin-\", crate_name!()))\n                    .tempfile()\n                    .map_err(Error::StdinTempFile)?,\n            );\n            let file = tmp_stdin.as_ref().unwrap();\n\n            // Fill temporary file with data, update list of files we upload, suggest name\n            file.as_file()\n                .write_all(&data)\n                .map_err(Error::StdinTempFile)?;\n            files = vec![file\n                .path()\n                .to_str()\n                .expect(\"failed to obtain file name for stdin buffer file\")];\n            file_name = file_name.or_else(|| Some(\"stdin.txt\".into()));\n        }\n\n        // Get API parameters\n        #[allow(unused_mut)]\n        let mut paths: Vec<_> = files\n            .into_iter()\n            .map(|p| Path::new(p).to_path_buf())\n            .collect();\n        let mut path = Path::new(paths.first().unwrap()).to_path_buf();\n        let host = matcher_upload.host();\n\n        // All paths must exist\n        // TODO: ensure the file exists and is accessible\n        for path in &paths {\n            if !path.exists() {\n                quit_error_msg(\n                    format!(\"the path '{}' does not exist\", path.to_str().unwrap_or(\"?\")),\n                    ErrorHintsBuilder::default().build().unwrap(),\n                );\n            }\n        }\n\n        // A temporary archive file, only used when archiving\n        // The temporary file is stored here, to ensure it's lifetime exceeds the upload process\n        #[allow(unused_mut)]\n        #[cfg(feature = \"archive\")]\n        let mut tmp_archive: Option<NamedTempFile> = None;\n\n        #[cfg(feature = \"archive\")]\n        {\n            // Determine whether to archive, we must archive for multiple files/directory\n            let mut archive = matcher_upload.archive();\n            if !archive {\n                if paths.len() > 1 {\n                    if prompt_yes(\n                        \"You've selected multiple files, only a single file may be uploaded.\\n\\\n                         Archive the files into a single file?\",\n                        Some(true),\n                        &matcher_main,\n                    ) {\n                        archive = true;\n                    } else {\n                        exit(1);\n                    }\n                } else if path.is_dir() {\n                    if prompt_yes(\n                        \"You've selected a directory, only a single file may be uploaded.\\n\\\n                         Archive the directory into a single file?\",\n                        Some(true),\n                        &matcher_main,\n                    ) {\n                        archive = true;\n                    } else {\n                        exit(1);\n                    }\n                }\n            }\n\n            // Archive the selected file or directory\n            if archive {\n                eprintln!(\"Archiving...\");\n                let archive_extention = \".tar\";\n\n                // Create a new temporary file to write the archive to\n                tmp_archive = Some(\n                    TempBuilder::new()\n                        .prefix(&format!(\".{}-archive-\", crate_name!()))\n                        .suffix(archive_extention)\n                        .tempfile()\n                        .map_err(ArchiveError::TempFile)?,\n                );\n                if let Some(tmp_archive) = &tmp_archive {\n                    // Get the path, and the actual file\n                    let archive_path = tmp_archive.path().to_path_buf();\n                    let archive_file = tmp_archive\n                        .as_file()\n                        .try_clone()\n                        .map_err(ArchiveError::CloneHandle)?;\n\n                    // Select the file name to use if not set\n                    if file_name.is_none() {\n                        // Derive name from given file\n                        if paths.len() == 1 {\n                            file_name = Some(\n                                path.canonicalize()\n                                    .map_err(|err| ArchiveError::FileName(Some(err)))?\n                                    .file_name()\n                                    .ok_or(ArchiveError::FileName(None))?\n                                    .to_str()\n                                    .map(|s| s.to_owned())\n                                    .ok_or(ArchiveError::FileName(None))?,\n                            );\n                        } else {\n                            // Unable to derive file name from paths, generate random\n                            file_name = Some(format!(\"ffsend-archive-{}\", rand_alphanum_string(8)));\n                        }\n                    }\n\n                    // Get the current working directory, including working directory as highest possible root, canonicalize it\n                    let working_dir =\n                        current_dir().expect(\"failed to get current working directory\");\n                    let shared_dir = {\n                        let mut paths = paths.clone();\n                        paths.push(working_dir.clone());\n                        match shared_dir(paths) {\n                            Some(p) => p,\n                            None => quit_error_msg(\n                                \"when archiving, all files must be within a same directory\",\n                                ErrorHintsBuilder::default().verbose(false).build().unwrap(),\n                            ),\n                        }\n                    };\n\n                    // Build an archiver, append each file\n                    let mut archiver = Archiver::new(archive_file);\n                    for path in &paths {\n                        // Canonicalize the path\n                        let mut path = Path::new(path).to_path_buf();\n                        if let Ok(p) = path.canonicalize() {\n                            path = p;\n                        }\n\n                        // Find relative name to share dir, used to derive name from\n                        let name = diff_paths(&path, &shared_dir)\n                            .expect(\"failed to determine relative path of file to archive\");\n                        let name = name.to_str().expect(\"failed to get file path\");\n\n                        // Add file to archiver\n                        archiver\n                            .append_path(name, &path)\n                            .map_err(ArchiveError::AddFile)?;\n                    }\n\n                    // Finish the archival process, writes the archive file\n                    archiver.finish().map_err(ArchiveError::Write)?;\n\n                    // Append archive extension to name, set to upload archived file\n                    if let Some(ref mut file_name) = file_name {\n                        file_name.push_str(archive_extention);\n                    }\n                    path = archive_path;\n                    paths.clear();\n                }\n            }\n        }\n\n        // Quit with error when uploading multiple files or directory, if we cannot archive\n        #[cfg(not(feature = \"archive\"))]\n        {\n            if paths.len() > 1 {\n                quit_error_msg(\n                    \"uploading multiple files is not supported, ffsend must be compiled with 'archive' feature for this\",\n                    ErrorHintsBuilder::default()\n                        .verbose(false)\n                        .build()\n                        .unwrap(),\n                );\n            }\n            if path.is_dir() {\n                quit_error_msg(\n                    \"uploading a directory is not supported, ffsend must be compiled with 'archive' feature for this\",\n                    ErrorHintsBuilder::default()\n                        .verbose(false)\n                        .build()\n                        .unwrap(),\n                );\n            }\n        }\n\n        // Create a reqwest client capable for uploading files\n        let client_config = create_config(&matcher_main);\n        let client = client_config.clone().client(false);\n\n        // Determine the API version to use\n        let mut desired_version = matcher_main.api();\n        select_api_version(&client, host.clone(), &mut desired_version)?;\n        let api_version = desired_version.version().unwrap();\n\n        // We do not authenticate for now\n        let auth = false;\n\n        // TODO: extract this into external function\n        {\n            // Determine the max file size\n            // TODO: set false parameter to authentication state\n            let max_size = upload_size_max(api_version, auth);\n\n            // Get the file size, fail on empty files, warn about large files\n            if let Ok(size) = path.metadata().map(|m| m.len()) {\n                // Enforce files not being 0 bytes\n                if size == 0 && !matcher_main.force() {\n                    quit_error_msg(\n                        \"uploading a file with a size of 0 bytes is not supported\",\n                        ErrorHintsBuilder::default()\n                            .force(true)\n                            .verbose(false)\n                            .build()\n                            .unwrap(),\n                    )\n                }\n\n                // Enforce maximum file size\n                if size > max_size && !matcher_main.force() {\n                    // The file is too large, show an error and quit\n                    quit_error_msg(\n                        format!(\n                            \"the file size is {}, bigger than the maximum allowed of {}\",\n                            format_bytes(size),\n                            format_bytes(max_size),\n                        ),\n                        ErrorHintsBuilder::default()\n                            .force(true)\n                            .verbose(false)\n                            .build()\n                            .unwrap(),\n                    );\n                }\n\n                // Enforce maximum recommended size\n                if size > UPLOAD_SIZE_MAX_RECOMMENDED && !matcher_main.force() {\n                    // The file is larger than the recommended maximum, warn\n                    eprintln!(\n                        \"The file size is {}, bigger than the recommended maximum of {}\",\n                        format_bytes(size),\n                        format_bytes(UPLOAD_SIZE_MAX_RECOMMENDED),\n                    );\n\n                    // Prompt the user to continue, quit if the user answered no\n                    if !prompt_yes(\"Continue uploading?\", Some(true), &matcher_main) {\n                        eprintln!(\"Upload cancelled\");\n                        quit();\n                    }\n                }\n            } else {\n                print_error_msg(\"failed to check the file size, ignoring\");\n            }\n        }\n\n        // TODO: assert max expiry time for file\n\n        // Create a reqwest client capable for uploading files\n        let transfer_client = client_config.client(true);\n\n        // Create a progress bar reporter\n        let progress_bar = Arc::new(Mutex::new(ProgressBar::new_upload()));\n\n        // Build a parameters object to set for the file\n        let params = {\n            // Build the parameters data object\n            let params = ParamsDataBuilder::default()\n                .download_limit(\n                    matcher_upload\n                        .download_limit(&matcher_main, api_version, auth)\n                        .map(|d| d as u8),\n                )\n                .expiry_time(matcher_upload.expiry_time(&matcher_main, api_version, auth))\n                .build()\n                .unwrap();\n\n            // Wrap the data in an option if not empty\n            if params.is_empty() {\n                None\n            } else {\n                Some(params)\n            }\n        };\n\n        // Build the progress reporter\n        let progress_reporter: Arc<Mutex<dyn ProgressReporter>> = progress_bar;\n\n        // Get the password to use and whether it was generated\n        let password = matcher_upload.password();\n        let (password, password_generated) =\n            password.map(|(p, g)| (Some(p), g)).unwrap_or((None, false));\n\n        // Execute an upload action, obtain the URL\n        let reporter = if !matcher_main.quiet() {\n            Some(&progress_reporter)\n        } else {\n            None\n        };\n        let file = ApiUpload::new(\n            api_version,\n            host,\n            path.clone(),\n            file_name,\n            password.clone(),\n            params,\n        )\n        .invoke(&transfer_client, reporter)?;\n        #[allow(unused_mut)]\n        let mut url = file.download_url(true);\n\n        // Shorten the share URL if requested, prompt the user to confirm\n        #[cfg(feature = \"urlshorten\")]\n        {\n            if matcher_upload.shorten() {\n                if prompt_yes(\"URL shortening is a security risk. This shares the secret URL with a 3rd party.\\nDo you want to shorten the share URL?\", Some(false), &matcher_main) {\n                    match urlshorten::shorten_url(&client, &url) {\n                        Ok(short) => url = short,\n                        Err(err) => print_error(\n                            err.context(\"failed to shorten share URL, ignoring\")\n                                .compat(),\n                        ),\n                    }\n                }\n            }\n        }\n\n        // Report the result\n        if !matcher_main.quiet() {\n            // Create a table\n            let mut table = Table::new();\n            table.set_format(FormatBuilder::new().padding(0, 2).build());\n\n            // Show the original URL when shortening, verbose and different\n            #[cfg(feature = \"urlshorten\")]\n            {\n                let full_url = file.download_url(true);\n                if matcher_main.verbose() && matcher_upload.shorten() && url != full_url {\n                    table.add_row(Row::new(vec![\n                        Cell::new(\"Full share link:\"),\n                        Cell::new(full_url.as_str()),\n                    ]));\n                }\n            }\n\n            if matcher_main.verbose() {\n                // Show the share URL\n                table.add_row(Row::new(vec![\n                    Cell::new(\"Share link:\"),\n                    Cell::new(url.as_str()),\n                ]));\n\n                // Show a generate passphrase\n                if password_generated {\n                    table.add_row(Row::new(vec![\n                        Cell::new(\"Passphrase:\"),\n                        Cell::new(&password.unwrap_or(\"?\".into())),\n                    ]));\n                }\n\n                // Show the owner token\n                table.add_row(Row::new(vec![\n                    Cell::new(\"Owner token:\"),\n                    Cell::new(file.owner_token().unwrap()),\n                ]));\n            } else {\n                table.add_row(Row::new(vec![Cell::new(url.as_str())]));\n\n                // Show a generate passphrase\n                if password_generated {\n                    table.add_row(Row::new(vec![Cell::new(&password.unwrap_or(\"?\".into()))]));\n                }\n            }\n\n            table.printstd();\n        } else {\n            println!(\"{}\", url);\n        }\n\n        // Add the file to the history manager\n        #[cfg(feature = \"history\")]\n        history_tool::add(&matcher_main, file.clone(), false);\n\n        // Open the URL in the browser\n        if matcher_upload.open() {\n            if let Err(err) = open_url(&url) {\n                print_error(err.context(\"failed to open the share link in the browser\"));\n            };\n        }\n\n        // Copy the URL or command to the user's clipboard\n        #[cfg(feature = \"clipboard\")]\n        {\n            if let Some(copy_mode) = matcher_upload.copy() {\n                if let Err(err) = set_clipboard(copy_mode.build(url.as_str())) {\n                    print_error(\n                        err.context(\"failed to copy the share link to the clipboard, ignoring\"),\n                    );\n                }\n            }\n        }\n\n        // Print a QR code for the share URL\n        #[cfg(feature = \"qrcode\")]\n        {\n            if matcher_upload.qrcode() {\n                if let Err(err) = print_qr(url.as_str()) {\n                    print_error(err.context(\"failed to print QR code, ignoring\").compat());\n                }\n            }\n        }\n\n        // Close the temporary stdin buffer file, to ensure it's removed\n        if let Some(tmp_stdin) = tmp_stdin.take() {\n            if let Err(err) = tmp_stdin.close() {\n                print_error(\n                    err.context(\"failed to clean up temporary stdin buffer file, ignoring\")\n                        .compat(),\n                );\n            }\n        }\n\n        #[cfg(feature = \"archive\")]\n        {\n            // Close the temporary zip file, to ensure it's removed\n            if let Some(tmp_archive) = tmp_archive.take() {\n                if let Err(err) = tmp_archive.close() {\n                    print_error(\n                        err.context(\"failed to clean up temporary archive file, ignoring\")\n                            .compat(),\n                    );\n                }\n            }\n        }\n\n        // Delete local files after uploading\n        if matcher_upload.delete() {\n            for path in &paths {\n                if path.is_file() {\n                    if let Err(err) = fs::remove_file(path) {\n                        print_error(\n                            Error::Delete(err)\n                                .context(\"failed to delete local file after upload, ignoring\")\n                                .compat(),\n                        );\n                    }\n                } else {\n                    if let Err(err) = fs::remove_dir_all(path) {\n                        print_error(\n                            Error::Delete(err)\n                                .context(\"failed to delete local directory after upload, ignoring\")\n                                .compat(),\n                        );\n                    }\n                }\n            }\n        }\n\n        Ok(())\n    }\n}\n\n/// Find the deepest directory all given paths share.\n///\n/// This function canonicalizes the paths, make sure the paths exist.\n///\n/// Returns `None` if paths are using a different root.\n///\n/// # Examples\n///\n/// If the following paths are given:\n///\n/// - `/home/user/git/ffsend/src`\n/// - `/home/user/git/ffsend/src/main.rs`\n/// - `/home/user/git/ffsend/Cargo.toml`\n///\n/// The following is returned:\n///\n/// `/home/user/git/ffsend`\n#[cfg(feature = \"archive\")]\nfn shared_dir(paths: Vec<PathBuf>) -> Option<PathBuf> {\n    // Any path must be given\n    if paths.is_empty() {\n        return None;\n    }\n\n    // Build vector\n    let c: Vec<Vec<PathBuf>> = paths\n        .into_iter()\n        .map(|p| p.canonicalize().expect(\"failed to canonicalize path\"))\n        .map(|mut p| {\n            // Start with parent if current path is file\n            if p.is_file() {\n                p = match p.parent() {\n                    Some(p) => p.to_path_buf(),\n                    None => return vec![],\n                };\n            }\n\n            // Build list of path buffers for each path component\n            let mut items = vec![p];\n            #[allow(mutable_borrow_reservation_conflict)]\n            while let Some(item) = items.last().unwrap().parent() {\n                items.push(item.to_path_buf());\n            }\n\n            // Reverse as we built it in the wrong order\n            items.reverse();\n            items\n        })\n        .collect();\n\n    // Find the index at which the paths are last shared at by walking through indices\n    let i = (0..)\n        .take_while(|i| {\n            // Get path for first item, stop if none\n            let base = &c[0].get(*i);\n            if base.is_none() {\n                return false;\n            };\n\n            // All other paths must equal at this index\n            c.iter().skip(1).all(|p| &p.get(*i) == base)\n        })\n        .last();\n\n    // Find the shared path\n    i.map(|i| c[0][i].to_path_buf())\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Selecting the API version to use failed.\n    // TODO: enable `api` hint!\n    #[fail(display = \"failed to select API version to use\")]\n    Version(#[cause] VersionError),\n\n    /// An error occurred while archiving the file to upload.\n    #[cfg(feature = \"archive\")]\n    #[fail(display = \"failed to archive file to upload\")]\n    Archive(#[cause] ArchiveError),\n\n    /// An error occurred while uploading the file.\n    #[fail(display = \"\")]\n    Upload(#[cause] UploadError),\n\n    /// An error occurred while deleting a local file after upload.\n    #[fail(display = \"failed to delete local file\")]\n    Delete(#[cause] IoError),\n\n    /// An error occurred while reading data from stdin.\n    #[fail(display = \"failed to read data from stdin\")]\n    Stdin(#[cause] StdinErr),\n\n    /// An error occurred while creating the temporary stdin file.\n    #[fail(display = \"failed to create temporary stdin buffer file\")]\n    StdinTempFile(#[cause] IoError),\n}\n\nimpl From<VersionError> for Error {\n    fn from(err: VersionError) -> Error {\n        Error::Version(err)\n    }\n}\n\n#[cfg(feature = \"archive\")]\nimpl From<ArchiveError> for Error {\n    fn from(err: ArchiveError) -> Error {\n        Error::Archive(err)\n    }\n}\n\nimpl From<UploadError> for Error {\n    fn from(err: UploadError) -> Error {\n        Error::Upload(err)\n    }\n}\n\n#[cfg(feature = \"archive\")]\n#[derive(Debug, Fail)]\npub enum ArchiveError {\n    /// An error occurred while creating the temporary archive file.\n    #[fail(display = \"failed to create temporary archive file\")]\n    TempFile(#[cause] IoError),\n\n    /// An error occurred while internally cloning the handle to the temporary archive file.\n    #[fail(display = \"failed to clone handle to temporary archive file\")]\n    CloneHandle(#[cause] IoError),\n\n    /// Failed to infer a file name for the archive.\n    #[fail(display = \"failed to infer a file name for the archive\")]\n    FileName(Option<IoError>),\n\n    /// Failed to add a file or directory to the archive.\n    #[fail(display = \"failed to add file to the archive\")]\n    AddFile(#[cause] IoError),\n\n    /// Failed to write the created archive to the disk.\n    #[fail(display = \"failed to write archive to disk\")]\n    Write(#[cause] IoError),\n}\n"
  },
  {
    "path": "src/action/version.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::action::version::{Error as VersionError, Version as ApiVersion};\n\nuse crate::client::create_config;\nuse crate::cmd::matcher::main::MainMatcher;\nuse crate::cmd::matcher::{version::VersionMatcher, Matcher};\nuse crate::error::ActionError;\n\n/// A file version action.\npub struct Version<'a> {\n    cmd_matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> Version<'a> {\n    /// Construct a new version action.\n    pub fn new(cmd_matches: &'a ArgMatches<'a>) -> Self {\n        Self { cmd_matches }\n    }\n\n    /// Invoke the version action.\n    // TODO: create a trait for this method\n    pub fn invoke(&self) -> Result<(), ActionError> {\n        // Create the command matchers\n        let matcher_version = VersionMatcher::with(self.cmd_matches).unwrap();\n        let matcher_main = MainMatcher::with(self.cmd_matches).unwrap();\n\n        // Get the host\n        let host = matcher_version.host();\n\n        // Create a reqwest client\n        let client_config = create_config(&matcher_main);\n        let client = client_config.client(false);\n\n        // Make sure the file version\n        let response = ApiVersion::new(host).invoke(&client);\n\n        // Print the result\n        match response {\n            Ok(v) => println!(\"API version: {}\", v),\n            Err(VersionError::Unknown) => println!(\"Version: unknown\"),\n            Err(VersionError::Unsupported(v)) => println!(\"Version: {} (unsupported)\", v),\n            Err(e) => return Err(e.into()),\n        }\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// An error occurred while attempting to determine the Send server version.\n    #[fail(display = \"failed to check the server version\")]\n    Version(#[cause] VersionError),\n}\n\nimpl From<VersionError> for Error {\n    fn from(err: VersionError) -> Error {\n        Error::Version(err)\n    }\n}\n"
  },
  {
    "path": "src/archive/archive.rs",
    "content": "use std::io::{Error as IoError, Read};\nuse std::path::Path;\n\nuse tar::Archive as TarArchive;\n\npub type Result<T> = ::std::result::Result<T, IoError>;\n\npub struct Archive<R: Read> {\n    /// The tar archive\n    inner: TarArchive<R>,\n}\n\nimpl<R: Read> Archive<R> {\n    /// Construct a new archive extractor.\n    pub fn new(reader: R) -> Archive<R> {\n        Archive {\n            inner: TarArchive::new(reader),\n        }\n    }\n\n    /// Extract the archive to the given destination.\n    pub fn extract<P: AsRef<Path>>(&mut self, destination: P) -> Result<()> {\n        self.inner.unpack(destination)\n    }\n}\n"
  },
  {
    "path": "src/archive/archiver.rs",
    "content": "use std::fs::File;\nuse std::io::{Error as IoError, Write};\nuse std::path::Path;\n\nuse tar::Builder as TarBuilder;\n\npub type Result<T> = ::std::result::Result<T, IoError>;\n\npub struct Archiver<W: Write> {\n    /// The tar builder.\n    inner: TarBuilder<W>,\n}\n\nimpl<W: Write> Archiver<W> {\n    /// Construct a new archive builder.\n    pub fn new(writer: W) -> Archiver<W> {\n        Archiver {\n            inner: TarBuilder::new(writer),\n        }\n    }\n\n    /// Add the entry at the given `src` path, to the given relative `path` in the archive.\n    ///\n    /// If a directory path is given, the whole directory including it's contents is added to the\n    /// archive.\n    ///\n    /// If no entry exists at the given `src_path`, an error is returned.\n    pub fn append_path<P, Q>(&mut self, path: P, src_path: Q) -> Result<()>\n    where\n        P: AsRef<Path>,\n        Q: AsRef<Path>,\n    {\n        // Append the path as file or directory\n        if src_path.as_ref().is_file() {\n            self.append_file(path, &mut File::open(src_path)?)\n        } else if src_path.as_ref().is_dir() {\n            self.append_dir(path, src_path)\n        } else {\n            // TODO: return a IO NotFound error here!\n            panic!(\"Unable to append path to archive, not a file or directory\");\n        }\n    }\n\n    /// Append a file to the archive builder.\n    pub fn append_file<P>(&mut self, path: P, file: &mut File) -> Result<()>\n    where\n        P: AsRef<Path>,\n    {\n        self.inner.append_file(path, file)\n    }\n\n    /// Append a directory to the archive builder.\n    // TODO: Define a flag to add recursively or not\n    pub fn append_dir<P, Q>(&mut self, path: P, src_path: Q) -> Result<()>\n    where\n        P: AsRef<Path>,\n        Q: AsRef<Path>,\n    {\n        self.inner.append_dir_all(path, src_path)\n    }\n\n    // TODO: some description\n    pub fn finish(mut self) -> Result<()> {\n        self.inner.finish()\n    }\n}\n"
  },
  {
    "path": "src/archive/mod.rs",
    "content": "pub mod archive;\npub mod archiver;\n"
  },
  {
    "path": "src/client.rs",
    "content": "use std::time::Duration;\n\nuse ffsend_api::client::{ClientConfig, ClientConfigBuilder};\n\nuse crate::cmd::matcher::MainMatcher;\n\n/// Create a client configuration for ffsend actions.\n///\n/// A client configuration allows you to build a client, which must be passed to ffsend API\n/// actions.\n// TODO: properly handle errors, do not unwrap\npub fn create_config(matcher_main: &MainMatcher) -> ClientConfig {\n    // TODO: configure HTTP authentication properties\n    ClientConfigBuilder::default()\n        .timeout(to_duration(matcher_main.timeout()))\n        .transfer_timeout(to_duration(matcher_main.transfer_timeout()))\n        .basic_auth(matcher_main.basic_auth())\n        .build()\n        .expect(\"failed to create network client configuration\")\n}\n\n/// Convert the given number of seconds into an optional duration, used for clients.\npub fn to_duration(secs: u64) -> Option<Duration> {\n    if secs > 0 {\n        Some(Duration::from_secs(secs))\n    } else {\n        None\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/api.rs",
    "content": "use clap::{Arg, ArgMatches};\nuse ffsend_api::api::{DesiredVersion, Version};\n\nuse super::{CmdArg, CmdArgOption};\nuse crate::config::API_VERSION_DESIRED_DEFAULT;\nuse crate::util::{quit_error_msg, ErrorHints};\n\n/// The api argument.\npub struct ArgApi {}\n\nimpl CmdArg for ArgApi {\n    fn name() -> &'static str {\n        \"api\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"api\")\n            .long(\"api\")\n            .short(\"A\")\n            .value_name(\"VERSION\")\n            .env(\"FFSEND_API\")\n            .hide_env_values(true)\n            .global(true)\n            .help(\"Server API version to use, '-' to lookup\")\n            .long_help(\n                \"Server API version to use, one of:\\n\\\n                 2, 3: Send API versions\\n\\\n                 auto, -: probe server to determine\\\n                 \",\n            )\n    }\n}\n\nimpl<'a> CmdArgOption<'a> for ArgApi {\n    type Value = DesiredVersion;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // Get the version string\n        let version = match Self::value_raw(matches) {\n            Some(version) => version,\n            None => return API_VERSION_DESIRED_DEFAULT,\n        };\n\n        // Parse the lookup version string\n        if is_auto(version) {\n            return DesiredVersion::Lookup;\n        }\n\n        // Parse the given API version\n        match Version::parse(version) {\n            Ok(version) => DesiredVersion::Use(version),\n            Err(_) => quit_error_msg(\n                \"failed to determine given server API version, version unknown\",\n                ErrorHints::default(),\n            ),\n        }\n    }\n}\n\n/// Check whether the given API version argument means we've to probe the server for the proper\n/// version.\nfn is_auto(arg: &str) -> bool {\n    let arg = arg.trim().to_lowercase();\n    arg == \"a\" || arg == \"auto\" || arg == \"-\"\n}\n"
  },
  {
    "path": "src/cmd/arg/basic_auth.rs",
    "content": "use clap::{Arg, ArgMatches};\n\nuse super::{CmdArg, CmdArgOption};\n\n/// The basicauth argument.\npub struct ArgBasicAuth {}\n\nimpl CmdArg for ArgBasicAuth {\n    fn name() -> &'static str {\n        \"basic-auth\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"basic-auth\")\n            .long(\"basic-auth\")\n            .alias(\"basic-authentication\")\n            .alias(\"http-basic-authentication\")\n            .alias(\"http-basic-auth\")\n            .value_name(\"USER:PASSWORD\")\n            .env(\"FFSEND_BASIC_AUTH\")\n            .hide_env_values(true)\n            .global(true)\n            .help(\"Protected proxy HTTP basic authentication credentials (not FxA)\")\n    }\n}\n\nimpl<'a> CmdArgOption<'a> for ArgBasicAuth {\n    type Value = Option<(String, Option<String>)>;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // Get the authentication credentials\n        let raw = match Self::value_raw(matches) {\n            Some(raw) => raw,\n            None => return None,\n        };\n\n        // Split the properties\n        let mut iter = raw.splitn(2, ':');\n        Some((\n            iter.next().unwrap_or(\"\").to_owned(),\n            iter.next().map(|pass| pass.to_owned()),\n        ))\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/download_limit.rs",
    "content": "use clap::{Arg, ArgMatches};\nuse ffsend_api::api::Version as ApiVersion;\nuse ffsend_api::config::downloads_max;\n\nuse super::{CmdArg, CmdArgFlag, CmdArgOption};\nuse crate::cmd::matcher::MainMatcher;\nuse crate::util::{highlight, prompt_yes, quit};\n\n/// The download limit argument.\npub struct ArgDownloadLimit {}\n\nimpl ArgDownloadLimit {\n    pub fn value_checked<'a>(\n        matches: &ArgMatches<'a>,\n        main_matcher: &MainMatcher,\n        api_version: ApiVersion,\n        auth: bool,\n    ) -> Option<usize> {\n        // Get the download value\n        let mut downloads = Self::value(matches)?;\n\n        // Get number of allowed downloads, return if allowed or when forcing\n        let allowed = downloads_max(api_version, auth);\n        if allowed.contains(&downloads) || main_matcher.force() {\n            return Some(downloads);\n        }\n\n        // Prompt the user the specified downloads limit is invalid\n        let allowed_str = allowed\n            .iter()\n            .map(|value| format!(\"{}\", value))\n            .collect::<Vec<_>>()\n            .join(\", \");\n        eprintln!(\"The downloads limit must be one of: {}\", allowed_str);\n        if auth {\n            eprintln!(\"Use '{}' to force\", highlight(\"--force\"));\n        } else {\n            eprintln!(\n                \"Use '{}' to force, authenticate for higher limits\",\n                highlight(\"--force\")\n            );\n        }\n\n        // Ask to use closest limit, quit if user cancelled\n        let closest = closest(allowed, downloads);\n        if !prompt_yes(\n            &format!(\"Would you like to limit downloads to {} instead?\", closest),\n            None,\n            main_matcher,\n        ) {\n            quit();\n        }\n        downloads = closest;\n\n        Some(downloads)\n    }\n}\n\nimpl CmdArg for ArgDownloadLimit {\n    fn name() -> &'static str {\n        \"download-limit\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"download-limit\")\n            .long(\"download-limit\")\n            .short(\"d\")\n            .alias(\"downloads\")\n            .alias(\"download\")\n            .value_name(\"COUNT\")\n            .env(\"FFSEND_DOWNLOAD_LIMIT\")\n            .help(\"The file download limit\")\n    }\n}\n\nimpl CmdArgFlag for ArgDownloadLimit {}\n\nimpl<'a> CmdArgOption<'a> for ArgDownloadLimit {\n    type Value = Option<usize>;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // TODO: do not unwrap, report an error\n        Self::value_raw(matches).map(|d| d.parse::<usize>().expect(\"invalid download limit\"))\n    }\n}\n\n/// Find the closest value to `current` in the given `values` range.\nfn closest(values: &[usize], current: usize) -> usize {\n    // Own the values, sort and reverse, start with biggest first\n    let mut values = values.to_vec();\n    values.sort_unstable();\n\n    // Find the closest value, return it\n    *values\n        .iter()\n        .rev()\n        .map(|value| (value, (current as i64 - *value as i64).abs()))\n        .min_by_key(|value| value.1)\n        .expect(\"failed to find closest value, none given\")\n        .0\n}\n"
  },
  {
    "path": "src/cmd/arg/expiry_time.rs",
    "content": "use chrono::Duration;\nuse clap::{Arg, ArgMatches};\nuse failure::Fail;\nuse ffsend_api::api::Version as ApiVersion;\nuse ffsend_api::config::expiry_max;\n\nuse super::{CmdArg, CmdArgFlag, CmdArgOption};\nuse crate::cmd::matcher::MainMatcher;\nuse crate::util::{\n    format_duration, highlight, parse_duration, prompt_yes, quit, quit_error, ErrorHints,\n};\n\n/// The download limit argument.\npub struct ArgExpiryTime {}\n\nimpl ArgExpiryTime {\n    pub fn value_checked<'a>(\n        matches: &ArgMatches<'a>,\n        main_matcher: &MainMatcher,\n        api_version: ApiVersion,\n        auth: bool,\n    ) -> Option<usize> {\n        // Get the expiry time value\n        let mut expiry = Self::value(matches)?;\n\n        // Get expiry time, return if allowed or when forcing\n        let max = *expiry_max(api_version, auth).into_iter().max().unwrap();\n        if expiry <= max || main_matcher.force() {\n            return Some(expiry);\n        }\n\n        // Define function to format seconds\n        let format_secs = |secs: usize| format_duration(Duration::seconds(secs as i64));\n\n        // Prompt the user the specified expiry time is invalid\n        eprintln!(\n            \"The expiry time must equal to or less than: {}\",\n            format_secs(max),\n        );\n        if auth {\n            eprintln!(\"Use '{}' to force\", highlight(\"--force\"));\n        } else {\n            eprintln!(\n                \"Use '{}' to force, authenticate for higher limits\",\n                highlight(\"--force\")\n            );\n        }\n\n        // Ask to use maximum expiry time instead, quit if user cancelled\n        if !prompt_yes(\n            &format!(\n                \"Would you like to set expiry time to {} instead?\",\n                format_secs(max),\n            ),\n            None,\n            main_matcher,\n        ) {\n            quit();\n        }\n        expiry = max;\n\n        Some(expiry)\n    }\n}\n\nimpl CmdArg for ArgExpiryTime {\n    fn name() -> &'static str {\n        \"expiry-time\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"expiry-time\")\n            .long(\"expiry-time\")\n            .short(\"e\")\n            .alias(\"expire\")\n            .alias(\"expiry\")\n            .value_name(\"TIME\")\n            .env(\"FFSEND_EXPIRY_TIME\")\n            .help(\"The file expiry time\")\n    }\n}\n\nimpl CmdArgFlag for ArgExpiryTime {}\n\nimpl<'a> CmdArgOption<'a> for ArgExpiryTime {\n    type Value = Option<usize>;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        Self::value_raw(matches).map(|t| match parse_duration(t) {\n            Ok(seconds) => seconds,\n            Err(err) => quit_error(\n                err.context(\"specified invalid file expiry time\"),\n                ErrorHints::default(),\n            ),\n        })\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/gen_passphrase.rs",
    "content": "use chbs;\nuse clap::Arg;\n\nuse super::{CmdArg, CmdArgFlag};\n\n/// The passphrase generation argument.\npub struct ArgGenPassphrase {}\n\nimpl ArgGenPassphrase {\n    /// Generate a cryptographically secure passphrase that is easily\n    /// remembered using diceware.\n    pub fn gen_passphrase() -> String {\n        chbs::passphrase()\n    }\n}\n\nimpl CmdArg for ArgGenPassphrase {\n    fn name() -> &'static str {\n        \"gen-passphrase\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"gen-passphrase\")\n            .long(\"gen-passphrase\")\n            .alias(\"gen-password\")\n            .alias(\"generate-passphrase\")\n            .alias(\"generate-password\")\n            .short(\"P\")\n            .conflicts_with(\"password\")\n            .help(\"Protect the file with a generated passphrase\")\n    }\n}\n\nimpl CmdArgFlag for ArgGenPassphrase {}\n"
  },
  {
    "path": "src/cmd/arg/host.rs",
    "content": "use clap::{Arg, ArgMatches};\nuse failure::Fail;\nuse ffsend_api::url::Url;\n\nuse super::{CmdArg, CmdArgOption};\nuse crate::host::parse_host;\nuse crate::util::{quit_error, ErrorHints};\n\n/// The host argument.\npub struct ArgHost {}\n\nimpl CmdArg for ArgHost {\n    fn name() -> &'static str {\n        \"host\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"host\")\n            .long(\"host\")\n            .short(\"h\")\n            .value_name(\"URL\")\n            .default_value(\"https://send.vis.ee/\")\n            .env(\"FFSEND_HOST\")\n            .hide_env_values(true)\n            .help(\"The remote host to upload to\")\n    }\n}\n\nimpl<'a> CmdArgOption<'a> for ArgHost {\n    type Value = Url;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // Get the URL\n        let url = Self::value_raw(matches).expect(\"missing host\");\n\n        // Parse the URL\n        match parse_host(&url) {\n            Ok(url) => url,\n            Err(err) => quit_error(\n                err.context(\"failed to parse the given host\"),\n                ErrorHints::default(),\n            ),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/mod.rs",
    "content": "pub mod api;\npub mod basic_auth;\npub mod download_limit;\npub mod expiry_time;\npub mod gen_passphrase;\npub mod host;\npub mod owner;\npub mod password;\npub mod url;\n\n// Re-export to arg module\npub use self::api::ArgApi;\npub use self::basic_auth::ArgBasicAuth;\npub use self::download_limit::ArgDownloadLimit;\npub use self::expiry_time::ArgExpiryTime;\npub use self::gen_passphrase::ArgGenPassphrase;\npub use self::host::ArgHost;\npub use self::owner::ArgOwner;\npub use self::password::ArgPassword;\npub use self::url::ArgUrl;\n\nuse clap::{Arg, ArgMatches};\n\n/// A generic trait, for a reusable command argument struct.\n/// The `CmdArgFlag` and `CmdArgOption` traits further specify what kind of\n/// argument this is.\npub trait CmdArg {\n    /// Get the argument name that is used as main identifier.\n    fn name() -> &'static str;\n\n    /// Build the argument.\n    fn build<'a, 'b>() -> Arg<'a, 'b>;\n}\n\n/// This `CmdArg` specification defines that this argument may be tested as\n/// flag. This will allow to test whether the flag is present in the given\n/// matches.\npub trait CmdArgFlag: CmdArg {\n    /// Check whether the argument is present in the given matches.\n    fn is_present<'a>(matches: &ArgMatches<'a>) -> bool {\n        matches.is_present(Self::name())\n    }\n}\n\n/// This `CmdArg` specification defines that this argument may be tested as\n/// option. This will allow to fetch the value of the argument.\npub trait CmdArgOption<'a>: CmdArg {\n    /// The type of the argument value.\n    type Value;\n\n    /// Get the argument value.\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value;\n\n    /// Get the raw argument value, as a string reference.\n    fn value_raw<'b: 'a>(matches: &'a ArgMatches<'b>) -> Option<&'a str> {\n        matches.value_of(Self::name())\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/owner.rs",
    "content": "use clap::{Arg, ArgMatches};\n\nuse super::{CmdArg, CmdArgFlag, CmdArgOption};\nuse crate::cmd::matcher::{MainMatcher, Matcher};\nuse crate::util::prompt_owner_token;\n\n/// The owner argument.\npub struct ArgOwner {}\n\nimpl CmdArg for ArgOwner {\n    fn name() -> &'static str {\n        \"owner\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"owner\")\n            .long(\"owner\")\n            .short(\"o\")\n            .alias(\"owner-token\")\n            .value_name(\"TOKEN\")\n            .min_values(0)\n            .max_values(1)\n            .help(\"Specify the file owner token\")\n    }\n}\n\nimpl CmdArgFlag for ArgOwner {}\n\nimpl<'a> CmdArgOption<'a> for ArgOwner {\n    type Value = Option<String>;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // The owner token flag must be present\n        if !Self::is_present(matches) {\n            return None;\n        }\n\n        // Get the owner token from the argument if set\n        match Self::value_raw(matches) {\n            None => {}\n            p => return p.map(|p| p.into()),\n        }\n\n        // Create a main matcher\n        let matcher_main = MainMatcher::with(matches).unwrap();\n\n        // Prompt for the owner token\n        // TODO: should this be optional?\n        Some(prompt_owner_token(&matcher_main, false))\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/password.rs",
    "content": "use clap::{Arg, ArgMatches};\n\nuse super::{CmdArg, CmdArgFlag, CmdArgOption};\nuse crate::cmd::matcher::{MainMatcher, Matcher};\nuse crate::util::{check_empty_password, prompt_password};\n\n/// The password argument.\npub struct ArgPassword {}\n\nimpl CmdArg for ArgPassword {\n    fn name() -> &'static str {\n        \"password\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"password\")\n            .long(\"password\")\n            .short(\"p\")\n            .value_name(\"PASSWORD\")\n            .min_values(0)\n            .max_values(1)\n            .help(\"Unlock a password protected file\")\n    }\n}\n\nimpl CmdArgFlag for ArgPassword {}\n\nimpl<'a> CmdArgOption<'a> for ArgPassword {\n    type Value = Option<String>;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // The password flag must be present\n        if !Self::is_present(matches) {\n            return None;\n        }\n\n        // Create a main matcher\n        let matcher_main = MainMatcher::with(matches).unwrap();\n\n        // Get the password argument value, or prompt\n        let password = match Self::value_raw(matches) {\n            Some(password) => password.into(),\n            None => prompt_password(&matcher_main, false).unwrap(),\n        };\n\n        // Check for empty passwords\n        check_empty_password(&password, &matcher_main);\n\n        Some(password)\n    }\n}\n"
  },
  {
    "path": "src/cmd/arg/url.rs",
    "content": "use clap::{Arg, ArgMatches};\nuse failure::Fail;\nuse ffsend_api::url::Url;\n\nuse super::{CmdArg, CmdArgOption};\nuse crate::host::parse_host;\nuse crate::util::{quit_error, ErrorHints};\n\n/// The URL argument.\npub struct ArgUrl {}\n\nimpl CmdArg for ArgUrl {\n    fn name() -> &'static str {\n        \"URL\"\n    }\n\n    fn build<'b, 'c>() -> Arg<'b, 'c> {\n        Arg::with_name(\"URL\")\n            .required(true)\n            .multiple(false)\n            .help(\"The share URL\")\n    }\n}\n\nimpl<'a> CmdArgOption<'a> for ArgUrl {\n    type Value = Url;\n\n    fn value<'b: 'a>(matches: &'a ArgMatches<'b>) -> Self::Value {\n        // Get the URL\n        let url = Self::value_raw(matches).expect(\"missing URL\");\n\n        // Parse the URL\n        match parse_host(&url) {\n            Ok(url) => url,\n            Err(err) => quit_error(\n                err.context(\"failed to parse the given share URL\"),\n                ErrorHints::default(),\n            ),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cmd/handler.rs",
    "content": "#[cfg(feature = \"infer-command\")]\nuse std::ffi::OsString;\n\nuse clap::{App, AppSettings, Arg, ArgMatches};\n\nuse super::arg::{ArgApi, ArgBasicAuth, CmdArg};\n#[cfg(feature = \"history\")]\nuse super::matcher::HistoryMatcher;\nuse super::matcher::{\n    DebugMatcher, DeleteMatcher, DownloadMatcher, ExistsMatcher, GenerateMatcher, InfoMatcher,\n    Matcher, ParamsMatcher, PasswordMatcher, UploadMatcher, VersionMatcher,\n};\n#[cfg(feature = \"history\")]\nuse super::subcmd::CmdHistory;\nuse super::subcmd::{\n    CmdDebug, CmdDelete, CmdDownload, CmdExists, CmdGenerate, CmdInfo, CmdParams, CmdPassword,\n    CmdUpload, CmdVersion,\n};\n#[cfg(feature = \"infer-command\")]\nuse crate::config::INFER_COMMANDS;\nuse crate::config::{CLIENT_TIMEOUT, CLIENT_TRANSFER_TIMEOUT};\n#[cfg(feature = \"history\")]\nuse crate::util::app_history_file_path_string;\n#[cfg(feature = \"infer-command\")]\nuse crate::util::bin_name;\nuse crate::util::parse_duration;\n\n#[cfg(feature = \"history\")]\nlazy_static! {\n    /// The default history file\n    static ref DEFAULT_HISTORY_FILE: String = app_history_file_path_string();\n}\n\nlazy_static! {\n    /// The default client timeout in seconds as a string\n    static ref DEFAULT_TIMEOUT: String = format!(\"{}\", CLIENT_TIMEOUT);\n\n    /// The default client transfer timeout in seconds as a string\n    static ref DEFAULT_TRANSFER_TIMEOUT: String = format!(\"{}\", CLIENT_TRANSFER_TIMEOUT);\n\n    /// The about notice in command output.\n    static ref APP_ABOUT: String = format!(\n        \"{}\\n\\n\\\n            The default public Send host is provided by Tim Visee, @timvisee.\\n\\\n            Please consider to donate and help keep it running: https://vis.ee/donate\\\n            \",\n        crate_description!(),\n    );\n}\n\n/// CLI argument handler.\npub struct Handler<'a> {\n    /// The CLI matches.\n    matches: ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> Handler<'a> {\n    /// Build the application CLI definition.\n    pub fn build() -> App<'a, 'b> {\n        // Build the CLI application definition\n        let app = App::new(crate_name!())\n            .version(crate_version!())\n            .author(crate_authors!())\n            .about(APP_ABOUT.as_str())\n            .after_help(\"This application is not affiliated with Firefox or Mozilla.\")\n            .global_setting(AppSettings::GlobalVersion)\n            .global_setting(AppSettings::VersionlessSubcommands)\n            // TODO: enable below command when it doesn't break `p` anymore.\n            // .global_setting(AppSettings::InferSubcommands)\n            .arg(\n                Arg::with_name(\"force\")\n                    .long(\"force\")\n                    .short(\"f\")\n                    .global(true)\n                    .help(\"Force the action, ignore warnings\"),\n            )\n            .arg(\n                Arg::with_name(\"no-interact\")\n                    .long(\"no-interact\")\n                    .short(\"I\")\n                    .alias(\"no-interactive\")\n                    .alias(\"non-interactive\")\n                    .global(true)\n                    .help(\"Not interactive, do not prompt\"),\n            )\n            .arg(\n                Arg::with_name(\"yes\")\n                    .long(\"yes\")\n                    .short(\"y\")\n                    .alias(\"assume-yes\")\n                    .global(true)\n                    .help(\"Assume yes for prompts\"),\n            )\n            .arg(\n                Arg::with_name(\"timeout\")\n                    .long(\"timeout\")\n                    .short(\"t\")\n                    .alias(\"time\")\n                    .global(true)\n                    .value_name(\"SECONDS\")\n                    .help(\"Request timeout (0 to disable)\")\n                    .default_value(&DEFAULT_TIMEOUT)\n                    .hide_default_value(true)\n                    .env(\"FFSEND_TIMEOUT\")\n                    .hide_env_values(true)\n                    .validator(|arg| {\n                        parse_duration(&arg).map(drop).map_err(|_| {\n                            String::from(\n                            \"Timeout time must be a positive number of seconds, or 0 to disable.\"\n                        )\n                        })\n                    }),\n            )\n            .arg(\n                Arg::with_name(\"transfer-timeout\")\n                    .long(\"transfer-timeout\")\n                    .short(\"T\")\n                    .alias(\"trans-time\")\n                    .alias(\"trans-timeout\")\n                    .alias(\"transfer-time\")\n                    .alias(\"time-trans\")\n                    .alias(\"timeout-trans\")\n                    .alias(\"time-transfer\")\n                    .global(true)\n                    .value_name(\"SECONDS\")\n                    .help(\"Transfer timeout (0 to disable)\")\n                    .default_value(&DEFAULT_TRANSFER_TIMEOUT)\n                    .hide_default_value(true)\n                    .env(\"FFSEND_TRANSFER_TIMEOUT\")\n                    .hide_env_values(true)\n                    .validator(|arg| {\n                        parse_duration(&arg).map(drop).map_err(|_| {\n                            String::from(\n                            \"Timeout time must be a positive number of seconds, or 0 to disable.\"\n                        )\n                        })\n                    }),\n            )\n            .arg(\n                Arg::with_name(\"quiet\")\n                    .long(\"quiet\")\n                    .short(\"q\")\n                    .global(true)\n                    .help(\"Produce output suitable for logging and automation\"),\n            )\n            .arg(\n                Arg::with_name(\"verbose\")\n                    .long(\"verbose\")\n                    .short(\"v\")\n                    .multiple(true)\n                    .global(true)\n                    .help(\"Enable verbose information and logging\"),\n            )\n            .arg(ArgApi::build())\n            .arg(ArgBasicAuth::build())\n            .subcommand(CmdDebug::build())\n            .subcommand(CmdDelete::build())\n            .subcommand(CmdDownload::build().display_order(2))\n            .subcommand(CmdExists::build())\n            .subcommand(CmdGenerate::build())\n            .subcommand(CmdInfo::build())\n            .subcommand(CmdParams::build())\n            .subcommand(CmdPassword::build())\n            .subcommand(CmdUpload::build().display_order(1))\n            .subcommand(CmdVersion::build());\n\n        // With history support, a flag for the history file and incognito mode\n        #[cfg(feature = \"history\")]\n        let app = app\n            .arg(\n                Arg::with_name(\"history\")\n                    .long(\"history\")\n                    .short(\"H\")\n                    .value_name(\"FILE\")\n                    .global(true)\n                    .help(\"Use the specified history file\")\n                    .default_value(&DEFAULT_HISTORY_FILE)\n                    .hide_default_value(true)\n                    .env(\"FFSEND_HISTORY\")\n                    .hide_env_values(true),\n            )\n            .arg(\n                Arg::with_name(\"incognito\")\n                    .long(\"incognito\")\n                    .short(\"i\")\n                    .alias(\"incog\")\n                    .alias(\"private\")\n                    .alias(\"priv\")\n                    .global(true)\n                    .help(\"Don't update local history for actions\"),\n            )\n            .subcommand(CmdHistory::build());\n\n        // Disable color usage if compiled without color support\n        #[cfg(feature = \"no-color\")]\n        let app = app.global_setting(AppSettings::ColorNever);\n\n        app\n    }\n\n    /// Parse CLI arguments.\n    pub fn parse() -> Handler<'a> {\n        // Obtain the program arguments\n        #[allow(unused_mut)]\n        let mut args: Vec<_> = ::std::env::args_os().collect();\n\n        // Infer subcommand based on binary name\n        #[cfg(feature = \"infer-command\")]\n        Self::infer_subcommand(&mut args);\n\n        // Build the application CLI definition, get the matches\n        Handler {\n            matches: Handler::build().get_matches_from(args),\n        }\n    }\n\n    /// Infer subcommand when the binary has a predefined name,\n    /// modifying the given program arguments.\n    ///\n    /// If no subcommand could be inferred, the `args` list leaves unchanged.\n    /// See `crate::config::INFER_COMMANDS` for a list of commands.\n    ///\n    /// When the `ffsend` binary is called with such a name, the corresponding subcommand is\n    /// automatically inserted as argument. This also works when calling binaries through symbolic\n    /// or hard links.\n    #[cfg(feature = \"infer-command\")]\n    fn infer_subcommand(args: &mut Vec<OsString>) {\n        // Get the name of the called binary\n        let name = bin_name();\n\n        // Infer subcommands\n        for (bin, subcmd) in INFER_COMMANDS.iter() {\n            if &name == bin {\n                args.insert(1, subcmd.into());\n                break;\n            }\n        }\n    }\n\n    /// Get the raw matches.\n    pub fn matches(&'a self) -> &'a ArgMatches {\n        &self.matches\n    }\n\n    /// Get the debug sub command, if matched.\n    pub fn debug(&'a self) -> Option<DebugMatcher> {\n        DebugMatcher::with(&self.matches)\n    }\n\n    /// Get the delete sub command, if matched.\n    pub fn delete(&'a self) -> Option<DeleteMatcher> {\n        DeleteMatcher::with(&self.matches)\n    }\n\n    /// Get the download sub command, if matched.\n    pub fn download(&'a self) -> Option<DownloadMatcher> {\n        DownloadMatcher::with(&self.matches)\n    }\n\n    /// Get the exists sub command, if matched.\n    pub fn exists(&'a self) -> Option<ExistsMatcher> {\n        ExistsMatcher::with(&self.matches)\n    }\n\n    /// Get the generate sub command, if matched.\n    pub fn generate(&'a self) -> Option<GenerateMatcher> {\n        GenerateMatcher::with(&self.matches)\n    }\n\n    /// Get the history sub command, if matched.\n    #[cfg(feature = \"history\")]\n    pub fn history(&'a self) -> Option<HistoryMatcher> {\n        HistoryMatcher::with(&self.matches)\n    }\n\n    /// Get the info matcher, if that subcommand is entered.\n    pub fn info(&'a self) -> Option<InfoMatcher> {\n        InfoMatcher::with(&self.matches)\n    }\n\n    /// Get the parameters sub command, if matched.\n    pub fn params(&'a self) -> Option<ParamsMatcher> {\n        ParamsMatcher::with(&self.matches)\n    }\n\n    /// Get the password sub command, if matched.\n    pub fn password(&'a self) -> Option<PasswordMatcher> {\n        PasswordMatcher::with(&self.matches)\n    }\n\n    /// Get the upload sub command, if matched.\n    pub fn upload(&'a self) -> Option<UploadMatcher> {\n        UploadMatcher::with(&self.matches)\n    }\n\n    /// Get the version sub command, if matched.\n    pub fn version(&'a self) -> Option<VersionMatcher> {\n        VersionMatcher::with(&self.matches)\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/debug.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::url::Url;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgHost, CmdArgOption};\n\n/// The debug command matcher.\npub struct DebugMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> DebugMatcher<'a> {\n    /// Get the host to upload to.\n    ///\n    /// This method parses the host into an `Url`.\n    /// If the given host is invalid,\n    /// the program will quit with an error message.\n    pub fn host(&'a self) -> Url {\n        ArgHost::value(self.matches)\n    }\n}\n\nimpl<'a> Matcher<'a> for DebugMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"debug\")\n            .map(|matches| DebugMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/delete.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::url::Url;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgOwner, ArgUrl, CmdArgOption};\n\n/// The delete command matcher.\npub struct DeleteMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> DeleteMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n\n    /// Get the owner token.\n    pub fn owner(&'a self) -> Option<String> {\n        // TODO: just return a string reference here?\n        ArgOwner::value(self.matches).map(|token| token.to_owned())\n    }\n}\n\nimpl<'a> Matcher<'a> for DeleteMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"delete\")\n            .map(|matches| DeleteMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/download.rs",
    "content": "use std::path::PathBuf;\n\nuse clap::ArgMatches;\nuse ffsend_api::url::Url;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgPassword, ArgUrl, CmdArgOption};\n#[cfg(feature = \"archive\")]\nuse crate::util::env_var_present;\n\n/// The download command matcher.\npub struct DownloadMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> DownloadMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n\n    /// Guess the file share host, based on the file share URL.\n    ///\n    /// See `Self::url`.\n    pub fn guess_host(&'a self, url: Option<Url>) -> Url {\n        let mut url = url.unwrap_or(self.url());\n        url.set_path(\"\");\n        url.set_query(None);\n        url.set_fragment(None);\n        url\n    }\n\n    /// Get the password.\n    /// `None` is returned if no password was specified.\n    pub fn password(&'a self) -> Option<String> {\n        ArgPassword::value(self.matches)\n    }\n\n    /// The target file or directory to download the file to.\n    /// If a directory is given, the file name of the original uploaded file\n    /// will be used.\n    pub fn output(&'a self) -> PathBuf {\n        self.matches\n            .value_of(\"output\")\n            .map(PathBuf::from)\n            .unwrap_or_else(|| PathBuf::from(\"./\"))\n    }\n\n    /// Check whether to extract an archived file.\n    #[cfg(feature = \"archive\")]\n    pub fn extract(&self) -> bool {\n        self.matches.is_present(\"extract\") || env_var_present(\"FFSEND_EXTRACT\")\n    }\n}\n\nimpl<'a> Matcher<'a> for DownloadMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"download\")\n            .map(|matches| DownloadMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/exists.rs",
    "content": "use ffsend_api::url::Url;\n\nuse clap::ArgMatches;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgUrl, CmdArgOption};\n\n/// The exists command matcher.\npub struct ExistsMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> ExistsMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n}\n\nimpl<'a> Matcher<'a> for ExistsMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"exists\")\n            .map(|matches| ExistsMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/generate/completions.rs",
    "content": "use std::path::PathBuf;\nuse std::str::FromStr;\n\nuse clap::{ArgMatches, Shell};\n\nuse super::Matcher;\n\n/// The completions completions command matcher.\npub struct CompletionsMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> CompletionsMatcher<'a> {\n    /// Get the shells to generate completions for.\n    pub fn shells(&'a self) -> Vec<Shell> {\n        // Get the raw list of shells\n        let raw = self\n            .matches\n            .values_of(\"SHELL\")\n            .expect(\"no shells were given\");\n\n        // Parse the list of shell names, deduplicate\n        let mut shells: Vec<_> = raw\n            .into_iter()\n            .map(|name| name.trim().to_lowercase())\n            .map(|name| {\n                if name == \"all\" {\n                    Shell::variants()\n                        .iter()\n                        .map(|name| name.to_string())\n                        .collect()\n                } else {\n                    vec![name]\n                }\n            })\n            .flatten()\n            .collect();\n        shells.sort_unstable();\n        shells.dedup();\n\n        // Parse the shell names\n        shells\n            .into_iter()\n            .map(|name| Shell::from_str(&name).expect(\"failed to parse shell name\"))\n            .collect()\n    }\n\n    /// The target directory to output the shell completion files to.\n    pub fn output(&'a self) -> PathBuf {\n        self.matches\n            .value_of(\"output\")\n            .map(PathBuf::from)\n            .unwrap_or_else(|| PathBuf::from(\"./\"))\n    }\n}\n\nimpl<'a> Matcher<'a> for CompletionsMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"generate\")?\n            .subcommand_matches(\"completions\")\n            .map(|matches| CompletionsMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/generate/mod.rs",
    "content": "pub mod completions;\n\nuse clap::ArgMatches;\n\nuse super::Matcher;\nuse completions::CompletionsMatcher;\n\n/// The generate command matcher.\npub struct GenerateMatcher<'a> {\n    root: &'a ArgMatches<'a>,\n    _matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> GenerateMatcher<'a> {\n    /// Get the generate completions sub command, if matched.\n    pub fn matcher_completions(&'a self) -> Option<CompletionsMatcher> {\n        CompletionsMatcher::with(&self.root)\n    }\n}\n\nimpl<'a> Matcher<'a> for GenerateMatcher<'a> {\n    fn with(root: &'a ArgMatches) -> Option<Self> {\n        root.subcommand_matches(\"generate\")\n            .map(|matches| GenerateMatcher {\n                root,\n                _matches: matches,\n            })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/history.rs",
    "content": "use clap::ArgMatches;\nuse failure::Fail;\nuse ffsend_api::url::Url;\n\nuse super::Matcher;\nuse crate::host::parse_host;\nuse crate::util::{quit_error, ErrorHints};\n\n/// The history command matcher.\npub struct HistoryMatcher<'a> {\n    #[allow(unused)]\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a> HistoryMatcher<'a> {\n    /// Check whether to clear all history.\n    pub fn clear(&self) -> bool {\n        self.matches.is_present(\"clear\")\n    }\n\n    /// Check whether to remove a given entry from the history.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn rm(&'a self) -> Option<Url> {\n        // Get the URL\n        let url = self.matches.value_of(\"rm\")?;\n\n        // Parse the URL\n        match parse_host(&url) {\n            Ok(url) => Some(url),\n            Err(err) => quit_error(\n                err.context(\"failed to parse the given share URL\"),\n                ErrorHints::default(),\n            ),\n        }\n    }\n}\n\nimpl<'a> Matcher<'a> for HistoryMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"history\")\n            .map(|matches| HistoryMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/info.rs",
    "content": "use ffsend_api::url::Url;\n\nuse clap::ArgMatches;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgOwner, ArgPassword, ArgUrl, CmdArgOption};\n\n/// The info command matcher.\npub struct InfoMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> InfoMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n\n    /// Get the owner token.\n    pub fn owner(&'a self) -> Option<String> {\n        // TODO: just return a string reference here?\n        ArgOwner::value(self.matches).map(|token| token.to_owned())\n    }\n\n    /// Get the password.\n    /// `None` is returned if no password was specified.\n    pub fn password(&'a self) -> Option<String> {\n        ArgPassword::value(self.matches)\n    }\n}\n\nimpl<'a> Matcher<'a> for InfoMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"info\")\n            .map(|matches| InfoMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/main.rs",
    "content": "#[cfg(feature = \"history\")]\nuse std::path::PathBuf;\n\nuse clap::ArgMatches;\nuse ffsend_api::api::DesiredVersion;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgApi, ArgBasicAuth, CmdArgOption};\nuse crate::util::{env_var_present, parse_duration};\n#[cfg(feature = \"history\")]\nuse crate::util::{quit_error_msg, ErrorHintsBuilder};\n\n/// The main command matcher.\npub struct MainMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> MainMatcher<'a> {\n    /// Check whether to force.\n    pub fn force(&self) -> bool {\n        self.matches.is_present(\"force\") || env_var_present(\"FFSEND_FORCE\")\n    }\n\n    /// Check whether to use no-interact mode.\n    pub fn no_interact(&self) -> bool {\n        self.matches.is_present(\"no-interact\") || env_var_present(\"FFSEND_NO_INTERACT\")\n    }\n\n    /// Check whether to assume yes.\n    pub fn assume_yes(&self) -> bool {\n        self.matches.is_present(\"yes\") || env_var_present(\"FFSEND_YES\")\n    }\n\n    /// Get the desired API version to use.\n    pub fn api(&'a self) -> DesiredVersion {\n        ArgApi::value(self.matches)\n    }\n\n    /// Get basic HTTP authentication credentials to use.\n    pub fn basic_auth(&'a self) -> Option<(String, Option<String>)> {\n        ArgBasicAuth::value(self.matches)\n    }\n\n    /// Get the history file to use.\n    #[cfg(feature = \"history\")]\n    pub fn history(&self) -> PathBuf {\n        // Get the path\n        let path = self.matches.value_of(\"history\").map(PathBuf::from);\n\n        // Ensure the path is correct\n        match path {\n            Some(path) => path,\n            None => quit_error_msg(\n                \"history file path not set\",\n                ErrorHintsBuilder::default()\n                    .history(true)\n                    .verbose(false)\n                    .build()\n                    .unwrap(),\n            ),\n        }\n    }\n\n    /// Get the timeout in seconds\n    pub fn timeout(&self) -> u64 {\n        self.matches\n            .value_of(\"timeout\")\n            .and_then(|arg| parse_duration(arg).ok())\n            .expect(\"invalid timeout value\") as u64\n    }\n\n    /// Get the transfer timeout in seconds\n    pub fn transfer_timeout(&self) -> u64 {\n        self.matches\n            .value_of(\"transfer-timeout\")\n            .and_then(|arg| parse_duration(arg).ok())\n            .expect(\"invalid transfer-timeout value\") as u64\n    }\n\n    /// Check whether we are incognito from the file history.\n    #[cfg(feature = \"history\")]\n    pub fn incognito(&self) -> bool {\n        self.matches.is_present(\"incognito\") || env_var_present(\"FFSEND_INCOGNITO\")\n    }\n\n    /// Check whether quiet mode is used.\n    pub fn quiet(&self) -> bool {\n        !self.verbose() && (self.matches.is_present(\"quiet\") || env_var_present(\"FFSEND_QUIET\"))\n    }\n\n    /// Check whether verbose mode is used.\n    pub fn verbose(&self) -> bool {\n        self.matches.is_present(\"verbose\") || env_var_present(\"FFSEND_VERBOSE\")\n    }\n}\n\nimpl<'a> Matcher<'a> for MainMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        Some(MainMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/mod.rs",
    "content": "pub mod debug;\npub mod delete;\npub mod download;\npub mod exists;\npub mod generate;\n#[cfg(feature = \"history\")]\npub mod history;\npub mod info;\npub mod main;\npub mod params;\npub mod password;\npub mod upload;\npub mod version;\n\n// Re-export to matcher module\npub use self::debug::DebugMatcher;\npub use self::delete::DeleteMatcher;\npub use self::download::DownloadMatcher;\npub use self::exists::ExistsMatcher;\npub use self::generate::GenerateMatcher;\n#[cfg(feature = \"history\")]\npub use self::history::HistoryMatcher;\npub use self::info::InfoMatcher;\npub use self::main::MainMatcher;\npub use self::params::ParamsMatcher;\npub use self::password::PasswordMatcher;\npub use self::upload::{CopyMode, UploadMatcher};\npub use self::version::VersionMatcher;\n\nuse clap::ArgMatches;\n\npub trait Matcher<'a>: Sized {\n    // Construct a new matcher instance from these argument matches.\n    fn with(matches: &'a ArgMatches) -> Option<Self>;\n}\n"
  },
  {
    "path": "src/cmd/matcher/params.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::api::Version as ApiVersion;\nuse ffsend_api::url::Url;\n\nuse super::Matcher;\nuse crate::cmd::{\n    arg::{ArgDownloadLimit, ArgOwner, ArgUrl, CmdArgOption},\n    matcher::MainMatcher,\n};\n\n/// The params command matcher.\npub struct ParamsMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> ParamsMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n\n    /// Get the owner token.\n    pub fn owner(&'a self) -> Option<String> {\n        // TODO: just return a string reference here?\n        ArgOwner::value(self.matches).map(|token| token.to_owned())\n    }\n\n    /// Get the download limit.\n    ///\n    /// If the download limit was the default, `None` is returned to not\n    /// explicitly set it.\n    pub fn download_limit(\n        &'a self,\n        main_matcher: &MainMatcher,\n        api_version: ApiVersion,\n        auth: bool,\n    ) -> Option<usize> {\n        ArgDownloadLimit::value_checked(self.matches, main_matcher, api_version, auth)\n    }\n}\n\nimpl<'a> Matcher<'a> for ParamsMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"parameters\")\n            .map(|matches| ParamsMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/password.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::url::Url;\nuse rpassword::prompt_password_stderr;\n\nuse crate::cmd::arg::{ArgGenPassphrase, ArgOwner, ArgPassword, ArgUrl, CmdArgFlag, CmdArgOption};\nuse crate::cmd::matcher::{MainMatcher, Matcher};\nuse crate::util::check_empty_password;\n\n/// The password command matcher.\npub struct PasswordMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> PasswordMatcher<'a> {\n    /// Get the file share URL.\n    ///\n    /// This method parses the URL into an `Url`.\n    /// If the given URL is invalid,\n    /// the program will quit with an error message.\n    pub fn url(&'a self) -> Url {\n        ArgUrl::value(self.matches)\n    }\n\n    /// Get the owner token.\n    pub fn owner(&'a self) -> Option<String> {\n        // TODO: just return a string reference here?\n        ArgOwner::value(self.matches).map(|token| token.to_owned())\n    }\n\n    /// Get the password.\n    ///\n    /// The password is returned in the following format:\n    /// `(password, generated)`\n    pub fn password(&'a self) -> (String, bool) {\n        // Generate a passphrase if requested\n        if ArgGenPassphrase::is_present(self.matches) {\n            return (ArgGenPassphrase::gen_passphrase(), true);\n        }\n\n        // Get the password, or prompt for it\n        let password = match ArgPassword::value(self.matches) {\n            Some(password) => password,\n            None => {\n                // Prompt for the password\n                // TODO: don't unwrap/expect\n                // TODO: create utility function for this\n                prompt_password_stderr(\"New password: \")\n                    .expect(\"failed to read password from stdin\")\n            }\n        };\n\n        // Create a main matcher\n        let matcher_main = MainMatcher::with(self.matches).unwrap();\n\n        // Check for empty passwords\n        check_empty_password(&password, &matcher_main);\n\n        (password, false)\n    }\n}\n\nimpl<'a> Matcher<'a> for PasswordMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"password\")\n            .map(|matches| PasswordMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/upload.rs",
    "content": "use clap::ArgMatches;\nuse ffsend_api::{api::Version as ApiVersion, config, url::Url};\n\nuse super::Matcher;\nuse crate::cmd::{\n    arg::{\n        ArgDownloadLimit, ArgExpiryTime, ArgGenPassphrase, ArgHost, ArgPassword, CmdArgFlag,\n        CmdArgOption,\n    },\n    matcher::MainMatcher,\n};\nuse crate::util::{bin_name, env_var_present, quit_error_msg, ErrorHintsBuilder};\n\n/// The upload command matcher.\npub struct UploadMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> UploadMatcher<'a> {\n    /// Get the selected file to upload.\n    // TODO: maybe return a file or path instance here\n    pub fn files(&'a self) -> Vec<&'a str> {\n        self.matches\n            .values_of(\"FILE\")\n            .expect(\"no file specified to upload\")\n            .collect()\n    }\n\n    /// The the name to use for the uploaded file.\n    /// If no custom name is given, none is returned.\n    // TODO: validate custom names, no path separators\n    // TODO: only allow extension renaming with force flag\n    pub fn name(&'a self) -> Option<&'a str> {\n        // Get the chosen file name\n        let name = self.matches.value_of(\"name\")?;\n\n        // The file name must not be empty\n        // TODO: allow to force an empty name here, and process empty names on downloading\n        if name.trim().is_empty() {\n            quit_error_msg(\n                \"the file name must not be empty\",\n                ErrorHintsBuilder::default()\n                    .force(false)\n                    .verbose(false)\n                    .build()\n                    .unwrap(),\n            );\n        }\n\n        Some(name)\n    }\n\n    /// Get the host to upload to.\n    ///\n    /// This method parses the host into an `Url`.\n    /// If the given host is invalid,\n    /// the program will quit with an error message.\n    pub fn host(&'a self) -> Url {\n        ArgHost::value(self.matches)\n    }\n\n    /// Get the password.\n    /// A generated passphrase will be returned if the user requested so,\n    /// otherwise the specified password is returned.\n    /// If no password was set, `None` is returned instead.\n    ///\n    /// The password is returned in the following format:\n    /// `(password, generated)`\n    pub fn password(&'a self) -> Option<(String, bool)> {\n        // Generate a passphrase if requested\n        if ArgGenPassphrase::is_present(self.matches) {\n            return Some((ArgGenPassphrase::gen_passphrase(), true));\n        }\n\n        // Use a specified password or use nothing\n        ArgPassword::value(self.matches).map(|password| (password, false))\n    }\n\n    /// Get the download limit.\n    ///\n    /// If the download limit was the default, `None` is returned to not\n    /// explicitly set it.\n    pub fn download_limit(\n        &'a self,\n        main_matcher: &MainMatcher,\n        api_version: ApiVersion,\n        auth: bool,\n    ) -> Option<usize> {\n        ArgDownloadLimit::value_checked(self.matches, main_matcher, api_version, auth).and_then(\n            |d| match d {\n                d if d == config::downloads_default(api_version, auth) => None,\n                d => Some(d),\n            },\n        )\n    }\n\n    /// Get the expiry time in seconds.\n    ///\n    /// If the expiry time was not set, `None` is returned.\n    pub fn expiry_time(\n        &'a self,\n        main_matcher: &MainMatcher,\n        api_version: ApiVersion,\n        auth: bool,\n    ) -> Option<usize> {\n        ArgExpiryTime::value_checked(self.matches, main_matcher, api_version, auth)\n    }\n\n    /// Check whether to archive the file to upload.\n    #[cfg(feature = \"archive\")]\n    pub fn archive(&self) -> bool {\n        self.matches.is_present(\"archive\") || env_var_present(\"FFSEND_ARCHIVE\")\n    }\n\n    /// Check whether to open the file URL in the user's browser.\n    pub fn open(&self) -> bool {\n        self.matches.is_present(\"open\") || env_var_present(\"FFSEND_OPEN\")\n    }\n\n    /// Check whether to to delete local files after uploading.\n    pub fn delete(&self) -> bool {\n        self.matches.is_present(\"delete\")\n    }\n\n    /// Check whether to copy the file URL in the user's clipboard, get the copy mode.\n    #[cfg(feature = \"clipboard\")]\n    pub fn copy(&self) -> Option<CopyMode> {\n        // Get the options\n        let copy = self.matches.is_present(\"copy\") || env_var_present(\"FFSEND_COPY\");\n        let copy_cmd = self.matches.is_present(\"copy-cmd\") || env_var_present(\"FFSEND_COPY_CMD\");\n\n        // Return the corresponding copy mode\n        if copy_cmd {\n            Some(CopyMode::DownloadCmd)\n        } else if copy {\n            Some(CopyMode::Url)\n        } else {\n            None\n        }\n    }\n\n    /// Check whether to shorten a share URL\n    #[cfg(feature = \"urlshorten\")]\n    pub fn shorten(&self) -> bool {\n        self.matches.is_present(\"shorten\")\n    }\n\n    /// Check whether to print a QR code for the share URL.\n    #[cfg(feature = \"qrcode\")]\n    pub fn qrcode(&self) -> bool {\n        self.matches.is_present(\"qrcode\")\n    }\n}\n\nimpl<'a> Matcher<'a> for UploadMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"upload\")\n            .map(|matches| UploadMatcher { matches })\n    }\n}\n\n/// The copy mode.\n#[derive(Debug, Copy, Clone)]\npub enum CopyMode {\n    /// Copy the public share link.\n    Url,\n\n    /// Copy an ffsend download command.\n    DownloadCmd,\n}\n\nimpl CopyMode {\n    /// Build the string to copy, based on the given `url` and current mode.\n    pub fn build(&self, url: &str) -> String {\n        match self {\n            CopyMode::Url => url.into(),\n            CopyMode::DownloadCmd => format!(\"{} download {}\", bin_name(), url),\n        }\n    }\n}\n"
  },
  {
    "path": "src/cmd/matcher/version.rs",
    "content": "use ffsend_api::url::Url;\n\nuse clap::ArgMatches;\n\nuse super::Matcher;\nuse crate::cmd::arg::{ArgHost, CmdArgOption};\n\n/// The version command matcher.\npub struct VersionMatcher<'a> {\n    matches: &'a ArgMatches<'a>,\n}\n\nimpl<'a: 'b, 'b> VersionMatcher<'a> {\n    /// Get the host to probe.\n    ///\n    /// This method parses the host into an `Url`.\n    /// If the given host is invalid,\n    /// the program will quit with an error message.\n    pub fn host(&'a self) -> Url {\n        ArgHost::value(self.matches)\n    }\n}\n\nimpl<'a> Matcher<'a> for VersionMatcher<'a> {\n    fn with(matches: &'a ArgMatches) -> Option<Self> {\n        matches\n            .subcommand_matches(\"version\")\n            .map(|matches| VersionMatcher { matches })\n    }\n}\n"
  },
  {
    "path": "src/cmd/mod.rs",
    "content": "pub mod arg;\npub mod handler;\npub mod matcher;\npub mod subcmd;\n\n// Reexport modules\npub use self::handler::Handler;\n"
  },
  {
    "path": "src/cmd/subcmd/debug.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgHost, CmdArg};\n\n/// The debug command definition.\npub struct CmdDebug;\n\nimpl CmdDebug {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"debug\")\n            .about(\"View debug information\")\n            .visible_alias(\"dbg\")\n            .arg(ArgHost::build().hidden(true))\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/delete.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgOwner, ArgUrl, CmdArg};\n\n/// The delete command definition.\npub struct CmdDelete;\n\nimpl CmdDelete {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"delete\")\n            .about(\"Delete a shared file\")\n            .visible_alias(\"del\")\n            .visible_alias(\"rm\")\n            .arg(ArgUrl::build())\n            .arg(ArgOwner::build())\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/download.rs",
    "content": "use clap::{App, Arg, SubCommand};\n\nuse crate::cmd::arg::{ArgPassword, ArgUrl, CmdArg};\n\n/// The download command definition.\npub struct CmdDownload;\n\nimpl CmdDownload {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        // Build the subcommand\n        #[allow(unused_mut)]\n        let mut cmd = SubCommand::with_name(\"download\")\n            .about(\"Download files\")\n            .visible_alias(\"d\")\n            .visible_alias(\"down\")\n            .arg(ArgUrl::build())\n            .arg(ArgPassword::build())\n            .arg(\n                Arg::with_name(\"output\")\n                    .long(\"output\")\n                    .short(\"o\")\n                    .alias(\"output-file\")\n                    .alias(\"out\")\n                    .alias(\"file\")\n                    .value_name(\"PATH\")\n                    .help(\"Output file or directory\"),\n            );\n\n        // Optional archive support\n        #[cfg(feature = \"archive\")]\n        {\n            cmd = cmd.arg(\n                Arg::with_name(\"extract\")\n                    .long(\"extract\")\n                    .short(\"e\")\n                    .alias(\"archive\")\n                    .alias(\"arch\")\n                    .alias(\"a\")\n                    .help(\"Extract an archived file\"),\n            )\n        }\n\n        cmd\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/exists.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgUrl, CmdArg};\n\n/// The exists command definition.\npub struct CmdExists;\n\nimpl CmdExists {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"exists\")\n            .about(\"Check whether a remote file exists\")\n            .visible_alias(\"e\")\n            .alias(\"exist\")\n            .arg(ArgUrl::build())\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/generate/completions.rs",
    "content": "use clap::{App, Arg, Shell, SubCommand};\n\n/// The generate completions command definition.\npub struct CmdCompletions;\n\nimpl CmdCompletions {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"completions\")\n            .about(\"Shell completions\")\n            .alias(\"completion\")\n            .alias(\"complete\")\n            .arg(\n                Arg::with_name(\"SHELL\")\n                    .help(\"Shell type to generate completions for\")\n                    .required(true)\n                    .multiple(true)\n                    .takes_value(true)\n                    .possible_value(\"all\")\n                    .possible_values(&Shell::variants())\n                    .case_insensitive(true),\n            )\n            .arg(\n                Arg::with_name(\"output\")\n                    .long(\"output\")\n                    .short(\"o\")\n                    .alias(\"output-dir\")\n                    .alias(\"out\")\n                    .alias(\"dir\")\n                    .value_name(\"DIR\")\n                    .help(\"Shell completion files output directory\"),\n            )\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/generate/mod.rs",
    "content": "pub mod completions;\n\nuse clap::{App, AppSettings, SubCommand};\n\nuse completions::CmdCompletions;\n\n/// The generate command definition.\npub struct CmdGenerate;\n\nimpl CmdGenerate {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"generate\")\n            .about(\"Generate assets\")\n            .visible_alias(\"gen\")\n            .setting(AppSettings::SubcommandRequiredElseHelp)\n            .subcommand(CmdCompletions::build())\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/history.rs",
    "content": "use clap::{App, Arg, SubCommand};\n\n/// The history command definition.\npub struct CmdHistory;\n\nimpl CmdHistory {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"history\")\n            .about(\"View file history\")\n            .visible_alias(\"h\")\n            .alias(\"ls\")\n            .arg(\n                Arg::with_name(\"rm\")\n                    .long(\"rm\")\n                    .short(\"R\")\n                    .alias(\"remove\")\n                    .value_name(\"URL\")\n                    .help(\"Remove history entry\"),\n            )\n            .arg(\n                Arg::with_name(\"clear\")\n                    .long(\"clear\")\n                    .short(\"C\")\n                    .alias(\"flush\")\n                    .help(\"Clear all history\"),\n            )\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/info.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgOwner, ArgPassword, ArgUrl, CmdArg};\n\n/// The info command definition.\npub struct CmdInfo;\n\nimpl CmdInfo {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"info\")\n            .about(\"Fetch info about a shared file\")\n            .visible_alias(\"i\")\n            .alias(\"information\")\n            .arg(ArgUrl::build())\n            .arg(ArgOwner::build())\n            .arg(ArgPassword::build())\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/mod.rs",
    "content": "pub mod debug;\npub mod delete;\npub mod download;\npub mod exists;\npub mod generate;\n#[cfg(feature = \"history\")]\npub mod history;\npub mod info;\npub mod params;\npub mod password;\npub mod upload;\npub mod version;\n\n// Re-export to cmd module\npub use self::debug::CmdDebug;\npub use self::delete::CmdDelete;\npub use self::download::CmdDownload;\npub use self::exists::CmdExists;\npub use self::generate::CmdGenerate;\n#[cfg(feature = \"history\")]\npub use self::history::CmdHistory;\npub use self::info::CmdInfo;\npub use self::params::CmdParams;\npub use self::password::CmdPassword;\npub use self::upload::CmdUpload;\npub use self::version::CmdVersion;\n"
  },
  {
    "path": "src/cmd/subcmd/params.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgDownloadLimit, ArgOwner, ArgUrl, CmdArg};\n\n/// The params command definition.\npub struct CmdParams;\n\nimpl CmdParams {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        // Create a list of parameter arguments, of which one is required\n        let param_args = [ArgDownloadLimit::name()];\n\n        SubCommand::with_name(\"parameters\")\n            .about(\"Change parameters of a shared file\")\n            .visible_alias(\"params\")\n            .alias(\"param\")\n            .alias(\"parameter\")\n            .arg(ArgUrl::build())\n            .arg(ArgOwner::build())\n            .arg(ArgDownloadLimit::build().required_unless_one(&param_args))\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/password.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgGenPassphrase, ArgOwner, ArgPassword, ArgUrl, CmdArg};\n\n/// The password command definition.\npub struct CmdPassword;\n\nimpl CmdPassword {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"password\")\n            .about(\"Change the password of a shared file\")\n            .visible_alias(\"pass\")\n            .visible_alias(\"p\")\n            .arg(ArgUrl::build())\n            .arg(ArgPassword::build().help(\"Specify a password, do not prompt\"))\n            .arg(ArgGenPassphrase::build())\n            .arg(ArgOwner::build())\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/upload.rs",
    "content": "use clap::{App, Arg, SubCommand};\n\nuse crate::cmd::arg::{\n    ArgDownloadLimit, ArgExpiryTime, ArgGenPassphrase, ArgHost, ArgPassword, CmdArg,\n};\n\n/// The upload command definition.\npub struct CmdUpload;\n\nimpl CmdUpload {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        // Build the subcommand\n        #[allow(unused_mut)]\n        let mut cmd = SubCommand::with_name(\"upload\")\n            .about(\"Upload files\")\n            .visible_alias(\"u\")\n            .visible_alias(\"up\")\n            .arg(\n                Arg::with_name(\"FILE\")\n                    .help(\"The file(s) to upload\")\n                    .required(true)\n                    .multiple(true),\n            )\n            .arg(ArgPassword::build().help(\"Protect the file with a password\"))\n            .arg(ArgGenPassphrase::build())\n            .arg(ArgDownloadLimit::build())\n            .arg(ArgExpiryTime::build())\n            .arg(ArgHost::build())\n            .arg(\n                Arg::with_name(\"name\")\n                    .long(\"name\")\n                    .short(\"n\")\n                    .alias(\"file\")\n                    .alias(\"f\")\n                    .value_name(\"NAME\")\n                    .help(\"Rename the file being uploaded\"),\n            )\n            .arg(\n                Arg::with_name(\"open\")\n                    .long(\"open\")\n                    .short(\"o\")\n                    .help(\"Open the share link in your browser\"),\n            )\n            .arg(\n                Arg::with_name(\"delete\")\n                    .long(\"delete\")\n                    .alias(\"rm\")\n                    .short(\"D\")\n                    .help(\"Delete local file after upload\"),\n            );\n\n        // Optional archive support\n        #[cfg(feature = \"archive\")]\n        {\n            cmd = cmd.arg(\n                Arg::with_name(\"archive\")\n                    .long(\"archive\")\n                    .short(\"a\")\n                    .alias(\"arch\")\n                    .help(\"Archive the upload in a single file\"),\n            )\n        }\n\n        // Optional clipboard support\n        #[cfg(feature = \"clipboard\")]\n        {\n            cmd = cmd\n                .arg(\n                    Arg::with_name(\"copy\")\n                        .long(\"copy\")\n                        .short(\"c\")\n                        .help(\"Copy the share link to your clipboard\")\n                        .conflicts_with(\"copy-cmd\"),\n                )\n                .arg(\n                    Arg::with_name(\"copy-cmd\")\n                        .long(\"copy-cmd\")\n                        .alias(\"copy-command\")\n                        .short(\"C\")\n                        .help(\"Copy the ffsend download command to your clipboard\")\n                        .conflicts_with(\"copy\"),\n                );\n        }\n\n        // Optional url shortening support\n        #[cfg(feature = \"urlshorten\")]\n        {\n            cmd = cmd.arg(\n                Arg::with_name(\"shorten\")\n                    .long(\"shorten\")\n                    .alias(\"short\")\n                    .alias(\"url-shorten\")\n                    .short(\"S\")\n                    .help(\"Shorten share URLs with a public service\"),\n            )\n        }\n\n        // Optional qrcode support\n        #[cfg(feature = \"qrcode\")]\n        {\n            cmd = cmd.arg(\n                Arg::with_name(\"qrcode\")\n                    .long(\"qrcode\")\n                    .alias(\"qr\")\n                    .short(\"Q\")\n                    .help(\"Print a QR code for the share URL\"),\n            )\n        }\n\n        cmd\n    }\n}\n"
  },
  {
    "path": "src/cmd/subcmd/version.rs",
    "content": "use clap::{App, SubCommand};\n\nuse crate::cmd::arg::{ArgHost, CmdArg};\n\n/// The version command definition.\npub struct CmdVersion;\n\nimpl CmdVersion {\n    pub fn build<'a, 'b>() -> App<'a, 'b> {\n        SubCommand::with_name(\"version\")\n            .about(\"Determine the Send server version\")\n            .alias(\"ver\")\n            .visible_alias(\"v\")\n            .arg(ArgHost::build())\n    }\n}\n"
  },
  {
    "path": "src/config.rs",
    "content": "#[cfg(feature = \"infer-command\")]\nuse std::collections::HashMap;\n\nuse ffsend_api::api::{DesiredVersion, Version};\n\n/// The timeout for the Send client for generic requests, `0` to disable.\npub const CLIENT_TIMEOUT: u64 = 30;\n\n/// The timeout for the Send client used to transfer (upload/download) files.\n/// Make sure this is big enough, or file uploads will be dropped. `0` to disable.\npub const CLIENT_TRANSFER_TIMEOUT: u64 = 24 * 60 * 60;\n\n/// The default desired version to select for the server API.\npub const API_VERSION_DESIRED_DEFAULT: DesiredVersion = DesiredVersion::Assume(API_VERSION_ASSUME);\n\n/// The default server API version to assume when it could not be determined.\n#[cfg(feature = \"send3\")]\npub const API_VERSION_ASSUME: Version = Version::V3;\n#[cfg(not(feature = \"send3\"))]\npub const API_VERSION_ASSUME: Version = Version::V2;\n\n#[cfg(feature = \"infer-command\")]\nlazy_static! {\n    /// Hashmap holding binary names to infer subcommands for.\n    ///\n    /// When the `ffsend` binary is called with such a name, the corresponding subcommand is\n    /// automatically inserted as argument. This also works when calling binaries through symbolic\n    /// or hard links.\n    pub static ref INFER_COMMANDS: HashMap<&'static str, &'static str> = {\n        let mut m = HashMap::new();\n        m.insert(\"ffput\", \"upload\");\n        m.insert(\"ffget\", \"download\");\n        m.insert(\"ffdel\", \"delete\");\n        m\n    };\n}\n"
  },
  {
    "path": "src/error.rs",
    "content": "use ffsend_api::action::delete::Error as DeleteError;\nuse ffsend_api::action::exists::Error as ExistsError;\nuse ffsend_api::action::params::Error as ParamsError;\nuse ffsend_api::action::password::Error as PasswordError;\nuse ffsend_api::action::version::Error as VersionError;\nuse ffsend_api::file::remote_file::FileParseError;\n\nuse crate::action::download::Error as CliDownloadError;\nuse crate::action::generate::completions::Error as CliGenerateCompletionsError;\n#[cfg(feature = \"history\")]\nuse crate::action::history::Error as CliHistoryError;\nuse crate::action::info::Error as CliInfoError;\nuse crate::action::upload::Error as CliUploadError;\n\n#[derive(Fail, Debug)]\npub enum Error {\n    /// An error occurred while invoking an action.\n    #[fail(display = \"\")]\n    Action(#[cause] ActionError),\n}\n\nimpl From<CliDownloadError> for Error {\n    fn from(err: CliDownloadError) -> Error {\n        Error::Action(ActionError::Download(err))\n    }\n}\n\nimpl From<CliInfoError> for Error {\n    fn from(err: CliInfoError) -> Error {\n        Error::Action(ActionError::Info(err))\n    }\n}\n\nimpl From<CliUploadError> for Error {\n    fn from(err: CliUploadError) -> Error {\n        Error::Action(ActionError::Upload(err))\n    }\n}\n\nimpl From<ActionError> for Error {\n    fn from(err: ActionError) -> Error {\n        Error::Action(err)\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum ActionError {\n    /// An error occurred while invoking the delete action.\n    #[fail(display = \"failed to delete the file\")]\n    Delete(#[cause] DeleteError),\n\n    /// An error occurred while invoking the download action.\n    #[fail(display = \"failed to download the requested file\")]\n    Download(#[cause] CliDownloadError),\n\n    /// An error occurred while invoking the exists action.\n    #[fail(display = \"failed to check whether the file exists\")]\n    Exists(#[cause] ExistsError),\n\n    /// An error occurred while generating completions.\n    #[fail(display = \"failed to generate shell completions\")]\n    GenerateCompletions(#[cause] CliGenerateCompletionsError),\n\n    /// An error occurred while processing the file history.\n    #[cfg(feature = \"history\")]\n    #[fail(display = \"failed to process the history\")]\n    History(#[cause] CliHistoryError),\n\n    /// An error occurred while invoking the info action.\n    #[fail(display = \"failed to fetch file info\")]\n    Info(#[cause] CliInfoError),\n\n    /// An error occurred while invoking the params action.\n    #[fail(display = \"failed to change the parameters\")]\n    Params(#[cause] ParamsError),\n\n    /// An error occurred while invoking the password action.\n    #[fail(display = \"failed to change the password\")]\n    Password(#[cause] PasswordError),\n\n    /// An error occurred while invoking the version action.\n    #[fail(display = \"failed to determine server version\")]\n    Version(#[cause] VersionError),\n\n    /// An error occurred while invoking the upload action.\n    #[fail(display = \"failed to upload the specified file\")]\n    Upload(#[cause] CliUploadError),\n\n    /// Failed to parse a share URL, it was invalid.\n    /// This error is not related to a specific action.\n    #[fail(display = \"invalid share URL\")]\n    InvalidUrl(#[cause] FileParseError),\n}\n\nimpl From<DeleteError> for ActionError {\n    fn from(err: DeleteError) -> ActionError {\n        ActionError::Delete(err)\n    }\n}\n\nimpl From<ExistsError> for ActionError {\n    fn from(err: ExistsError) -> ActionError {\n        ActionError::Exists(err)\n    }\n}\n\nimpl From<CliGenerateCompletionsError> for ActionError {\n    fn from(err: CliGenerateCompletionsError) -> ActionError {\n        ActionError::GenerateCompletions(err)\n    }\n}\n\n#[cfg(feature = \"history\")]\nimpl From<CliHistoryError> for ActionError {\n    fn from(err: CliHistoryError) -> ActionError {\n        ActionError::History(err)\n    }\n}\n\nimpl From<ParamsError> for ActionError {\n    fn from(err: ParamsError) -> ActionError {\n        ActionError::Params(err)\n    }\n}\n\nimpl From<PasswordError> for ActionError {\n    fn from(err: PasswordError) -> ActionError {\n        ActionError::Password(err)\n    }\n}\n\nimpl From<VersionError> for ActionError {\n    fn from(err: VersionError) -> ActionError {\n        ActionError::Version(err)\n    }\n}\n\nimpl From<FileParseError> for ActionError {\n    fn from(err: FileParseError) -> ActionError {\n        ActionError::InvalidUrl(err)\n    }\n}\n"
  },
  {
    "path": "src/history.rs",
    "content": "use std::fs;\nuse std::io::Error as IoError;\nuse std::path::PathBuf;\n\nuse failure::Fail;\nuse ffsend_api::{\n    file::remote_file::{FileParseError, RemoteFile},\n    url::Url,\n};\nuse toml::{de::Error as DeError, ser::Error as SerError};\nuse version_compare::Cmp;\n\nuse crate::util::{print_error, print_warning};\n\n/// The minimum supported history file version.\nconst VERSION_MIN: &str = \"0.0.1\";\n\n/// The maximum supported history file version.\nconst VERSION_MAX: &str = crate_version!();\n\n#[derive(Serialize, Deserialize)]\npub struct History {\n    /// The application version the history file was built with.\n    /// Used for compatibility checking.\n    version: Option<String>,\n\n    /// The file history.\n    files: Vec<RemoteFile>,\n\n    /// Whether the list of files has changed.\n    #[serde(skip)]\n    changed: bool,\n\n    /// An optional path to automatically save the history to.\n    #[serde(skip)]\n    autosave: Option<PathBuf>,\n}\n\nimpl History {\n    /// Construct a new history.\n    /// A path may be given to automatically save the history to once changed.\n    pub fn new(autosave: Option<PathBuf>) -> Self {\n        let mut history = History::default();\n        history.autosave = autosave;\n        history\n    }\n\n    /// Load the history from the given file.\n    pub fn load(path: PathBuf) -> Result<Self, LoadError> {\n        // Read the file to a string\n        let data = fs::read_to_string(&path)?;\n\n        // Parse the data, set the autosave path\n        let mut history: Self = toml::from_str(&data)?;\n        history.autosave = Some(path);\n\n        // Make sure the file version is supported\n        if history.version.is_none() {\n            print_warning(\"History file has no version, ignoring\");\n            history.version = Some(crate_version!().into());\n        } else {\n            // Get the version number from the file\n            let version = history.version.as_ref().unwrap();\n\n            if let Ok(true) = version_compare::compare_to(version, VERSION_MIN, Cmp::Lt) {\n                print_warning(\"history file version is too old, ignoring\");\n            } else if let Ok(true) = version_compare::compare_to(version, VERSION_MAX, Cmp::Gt) {\n                print_warning(\"history file has an unknown version, ignoring\");\n            }\n        }\n\n        // Garbage collect\n        history.gc();\n\n        Ok(history)\n    }\n\n    /// Load the history from the given file.\n    /// If the file doesn't exist, create a new empty history instance.\n    ///\n    /// Autosaving will be enabled, and will save to the given file path.\n    pub fn load_or_new(file: PathBuf) -> Result<Self, LoadError> {\n        if file.is_file() {\n            Self::load(file)\n        } else {\n            Ok(Self::new(Some(file)))\n        }\n    }\n\n    /// Save the history to the internal autosave file.\n    pub fn save(&mut self) -> Result<(), SaveError> {\n        // Garbage collect\n        self.gc();\n\n        // Get the path\n        let path = self.autosave.as_ref().ok_or(SaveError::NoPath)?;\n\n        // If we have no files, remove the history file if it exists\n        if self.files.is_empty() {\n            if path.is_file() {\n                fs::remove_file(&path).map_err(SaveError::Delete)?;\n            }\n            return Ok(());\n        }\n\n        // Ensure the file parent directories are available\n        if let Some(parent) = path.parent() {\n            fs::create_dir_all(parent)?;\n        }\n\n        // Set file permissions on unix based systems\n        #[cfg(unix)]\n        {\n            use std::fs::Permissions;\n            use std::os::unix::fs::PermissionsExt;\n\n            if !path.exists() {\n                let file = fs::File::create(path).map_err(SaveError::Write)?;\n\n                // Set Read/Write permissions for the user\n                file.set_permissions(Permissions::from_mode(0o600))\n                    .map_err(SaveError::SetPermissions)?;\n            }\n        }\n\n        // Build the data and write to a file\n        let data = toml::to_string(self)?;\n        fs::write(&path, data)?;\n\n        // There are no new changes, set the flag\n        self.changed = false;\n\n        Ok(())\n    }\n\n    /// Add the given remote file to the history.\n    /// If a file with the same ID as the given file exists,\n    /// the files are merged, see `RemoteFile::merge()`.\n    ///\n    /// If `overwrite` is set to true, the given file will overwrite\n    /// properties on the existing file.\n    pub fn add(&mut self, file: RemoteFile, overwrite: bool) {\n        // Merge any existing file with the same ID\n        {\n            // Find anything to merge\n            let merge_info: Vec<bool> = self\n                .files\n                .iter_mut()\n                .filter(|f| f.id() == file.id())\n                .map(|ref mut f| f.merge(&file, overwrite))\n                .collect();\n            let merged = !merge_info.is_empty();\n            let changed = merge_info.iter().any(|i| *i);\n\n            // Return if merged, update the changed state\n            if merged {\n                if changed {\n                    self.changed = true;\n                }\n                return;\n            }\n        }\n\n        // Add the file to the list\n        self.files.push(file);\n        self.changed = true;\n    }\n\n    /// Remove a file, matched by it's file ID.\n    ///\n    /// If any file was removed, true is returned.\n    pub fn remove(&mut self, id: &str) -> bool {\n        // Get the indices of files that have expired\n        let expired_indices: Vec<usize> = self\n            .files\n            .iter()\n            .enumerate()\n            .filter(|&(_, f)| f.id() == id)\n            .map(|(i, _)| i)\n            .collect();\n\n        // Remove these specific files\n        for i in expired_indices.iter().rev() {\n            self.files.remove(*i);\n        }\n\n        // Set the changed flag, and return\n        if expired_indices.is_empty() {\n            self.changed = true;\n        }\n        !expired_indices.is_empty()\n    }\n\n    /// Remove a file by the given URL.\n    ///\n    /// If any file was removed, true is returned.\n    pub fn remove_url(&mut self, url: Url) -> Result<bool, FileParseError> {\n        Ok(self.remove(RemoteFile::parse_url(url, None)?.id()))\n    }\n\n    /// Get all files.\n    pub fn files(&self) -> &Vec<RemoteFile> {\n        &self.files\n    }\n\n    /// Get a file from the history, based on the given remote file.\n    /// The file ID and host will be compared against all files in this history.\n    /// If multiple files exist within the history that are equal, only one is returned.\n    /// If no matching file was found, `None` is returned.\n    pub fn get_file(&self, file: &RemoteFile) -> Option<&RemoteFile> {\n        self.files\n            .iter()\n            .find(|f| f.id() == file.id() && f.host() == file.host())\n    }\n\n    /// Clear all history.\n    pub fn clear(&mut self) {\n        self.changed = !self.files.is_empty();\n        self.files.clear();\n    }\n\n    /// Garbage collect (remove) all files that have been expired,\n    /// as defined by their `expire_at` property.\n    ///\n    /// If the expiry property is None (thus unknown), the file will be kept.\n    ///\n    /// The number of expired files is returned.\n    pub fn gc(&mut self) -> usize {\n        // Get a list of expired files\n        let expired: Vec<RemoteFile> = self\n            .files\n            .iter()\n            .filter(|f| f.has_expired())\n            .cloned()\n            .collect();\n\n        // Remove the files\n        for f in &expired {\n            self.remove(f.id());\n        }\n\n        // Set the changed flag\n        if !expired.is_empty() {\n            self.changed = true;\n        }\n\n        // Return the number of expired files\n        expired.len()\n    }\n}\n\nimpl Drop for History {\n    fn drop(&mut self) {\n        // Automatically save if enabled and something was changed\n        if self.autosave.is_some() && self.changed {\n            // Save and report errors\n            if let Err(err) = self.save() {\n                print_error(err.context(\"failed to auto save history, ignoring\"));\n            }\n        }\n    }\n}\n\nimpl Default for History {\n    fn default() -> Self {\n        Self {\n            version: Some(crate_version!().into()),\n            files: Vec::new(),\n            changed: false,\n            autosave: None,\n        }\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum Error {\n    /// An error occurred while loading the history from a file.\n    #[fail(display = \"failed to load history from file\")]\n    Load(#[cause] LoadError),\n\n    /// An error occurred while saving the history to a file.\n    #[fail(display = \"failed to save history to file\")]\n    Save(#[cause] SaveError),\n}\n\nimpl From<LoadError> for Error {\n    fn from(err: LoadError) -> Self {\n        Error::Load(err)\n    }\n}\n\nimpl From<SaveError> for Error {\n    fn from(err: SaveError) -> Self {\n        Error::Save(err)\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum LoadError {\n    /// Failed to read the file contents from the given file.\n    #[fail(display = \"failed to read from the history file\")]\n    Read(#[cause] IoError),\n\n    /// Failed to parse the loaded file.\n    #[fail(display = \"failed to parse the file contents\")]\n    Parse(#[cause] DeError),\n}\n\nimpl From<IoError> for LoadError {\n    fn from(err: IoError) -> Self {\n        LoadError::Read(err)\n    }\n}\n\nimpl From<DeError> for LoadError {\n    fn from(err: DeError) -> Self {\n        LoadError::Parse(err)\n    }\n}\n\n#[derive(Debug, Fail)]\npub enum SaveError {\n    /// No autosave file path was present, failed to save.\n    #[fail(display = \"no autosave file path specified\")]\n    NoPath,\n\n    /// Failed to serialize the history for saving.\n    #[fail(display = \"failed to serialize the history for saving\")]\n    Serialize(#[cause] SerError),\n\n    /// Failed to write to the history file.\n    #[fail(display = \"failed to write to the history file\")]\n    Write(#[cause] IoError),\n\n    /// Failed to set file permissions to the history file.\n    #[fail(display = \"failed to set permissions to the history file\")]\n    SetPermissions(#[cause] IoError),\n\n    /// Failed to delete the history file, which was tried because there\n    /// are no history items to save.\n    #[fail(display = \"failed to delete history file, because history is empty\")]\n    Delete(#[cause] IoError),\n}\n\nimpl From<SerError> for SaveError {\n    fn from(err: SerError) -> Self {\n        SaveError::Serialize(err)\n    }\n}\n\nimpl From<IoError> for SaveError {\n    fn from(err: IoError) -> Self {\n        SaveError::Write(err)\n    }\n}\n"
  },
  {
    "path": "src/history_tool.rs",
    "content": "use failure::Fail;\nuse ffsend_api::file::remote_file::RemoteFile;\n\nuse crate::cmd::matcher::MainMatcher;\nuse crate::history::{Error as HistoryError, History};\nuse crate::util::print_error;\n\n/// Load the history from the given path, add the given file, and save it\n/// again.\n///\n/// When a file with the same ID already exists, the existing file is\n/// merged with this one. If `overwrite` is set to true, this file will\n/// overwrite properties in the already existing file when merging.\n///\n/// If there is no file at the given path, new history will be created.\nfn add_error(\n    matcher_main: &MainMatcher,\n    file: RemoteFile,\n    overwrite: bool,\n) -> Result<(), HistoryError> {\n    // Ignore if incognito\n    if matcher_main.incognito() {\n        return Ok(());\n    }\n\n    // Load the history, add the file, and save\n    let mut history = History::load_or_new(matcher_main.history())?;\n    history.add(file, overwrite);\n    history.save().map_err(|err| err.into())\n}\n\n/// Load the history from the given path, add the given file, and save it\n/// again.\n/// If there is no file at the given path, new history will be created.\n///\n/// When a file with the same ID already exists, the existing file is\n/// merged with this one. If `overwrite` is set to true, this file will\n/// overwrite properties in the already existing file when merging.\n///\n/// If an error occurred, the error is printed and ignored.\npub fn add(matcher_main: &MainMatcher, file: RemoteFile, overwrite: bool) {\n    if let Err(err) = add_error(matcher_main, file, overwrite) {\n        print_error(err.context(\"failed to add file to local history, ignoring\"));\n    }\n}\n\n/// Load the history from the given path, remove the given file by it's\n/// ID, and save it again.\n/// True is returned if any file was removed.\nfn remove_error(matcher_main: &MainMatcher, file: &RemoteFile) -> Result<bool, HistoryError> {\n    // Ignore if incognito\n    if matcher_main.incognito() {\n        return Ok(false);\n    }\n\n    // Load the history, remove the file, and save\n    let mut history = History::load_or_new(matcher_main.history())?;\n    let removed = history.remove(file.id());\n    history.save()?;\n    Ok(removed)\n}\n\n/// Load the history from the given path, remove the given file by it's\n/// ID, and save it again.\n/// True is returned if any file was removed.\npub fn remove(matcher_main: &MainMatcher, file: &RemoteFile) -> bool {\n    let result = remove_error(matcher_main, file);\n    let ok = result.is_ok();\n    if let Err(err) = result {\n        print_error(err.context(\"failed to remove file from local history, ignoring\"));\n    }\n    ok\n}\n\n/// Derive the file secret and owner token from the history for the given file.\n/// The newly derived properties will be set into the given borrowed remote file.\n/// This method may be used to automatically derive the properties for some file actions\n/// requiring an owner token or secret, to prevent the user from having to enter it manually.\n///\n/// If the file already has all properties set,\n/// nothing will be derived and `false` is returned.\n/// If an error occurred while deriving,\n/// the error is printed and `false` is returned.\n/// If there was no matching file in the history,\n/// and no properties could be derived, `false` is returned.\n/// Incognito mode does not have any effect on this method,\n/// as it won't ever change the history.\n///\n/// If any property was successfully derived, `true` is returned.\npub fn derive_file_properties(matcher_main: &MainMatcher, file: &mut RemoteFile) -> bool {\n    // Return if all properties are already set\n    if file.has_secret() && file.has_owner_token() {\n        return false;\n    }\n\n    // Load the history\n    let history = match History::load_or_new(matcher_main.history()) {\n        Ok(history) => history,\n        Err(err) => {\n            print_error(err.context(\"failed to derive file properties from history, ignoring\"));\n            return false;\n        }\n    };\n\n    // Find a matching file, grab and set the owner token if available\n    match history.get_file(file) {\n        Some(f) => {\n            // Set the secret\n            if f.has_secret() {\n                file.set_secret(f.secret_raw().clone());\n            }\n\n            // Set the owner token\n            if f.has_owner_token() {\n                file.set_owner_token(f.owner_token().cloned());\n            }\n\n            // Return whether any property was derived\n            f.has_secret() || f.has_owner_token()\n        }\n        None => false,\n    }\n}\n"
  },
  {
    "path": "src/host.rs",
    "content": "use ffsend_api::url::{ParseError, Url};\n\n/// Parse the given host string, into an URL.\npub fn parse_host(host: &str) -> Result<Url, HostError> {\n    // Trim\n    let host = host.trim();\n\n    // Make sure a valid scheme is prefixed\n    if !host.starts_with(\"https://\") && !host.starts_with(\"http://\") {\n        return Err(HostError::Scheme);\n    }\n\n    // Parse the URL, and map the errors\n    Url::parse(host).map_err(|err| match err {\n        ParseError::EmptyHost => HostError::Empty,\n        ParseError::InvalidPort => HostError::Port,\n        ParseError::InvalidIpv4Address => HostError::Ipv4,\n        ParseError::InvalidIpv6Address => HostError::Ipv6,\n        ParseError::InvalidDomainCharacter => HostError::DomainCharacter,\n        ParseError::RelativeUrlWithoutBase => HostError::NoBase,\n        err => HostError::Other(err),\n    })\n}\n\n/// An error that has occurred while parsing a host.\n#[derive(Debug, Fail)]\npub enum HostError {\n    /// The URL scheme is missing or invalid.\n    #[fail(display = \"the URL must have the 'https://' or 'http://' scheme\")]\n    Scheme,\n\n    /// The host address is empty.\n    #[fail(display = \"empty host address\")]\n    Empty,\n\n    /// The port number is invalid.\n    #[fail(display = \"invalid port\")]\n    Port,\n\n    /// The given IPv4 styled address is invalid.\n    #[fail(display = \"invalid IPv4 address in the host\")]\n    Ipv4,\n\n    /// The given IPv6 styled address is invalid.\n    #[fail(display = \"invalid IPv6 address in the host\")]\n    Ipv6,\n\n    /// The domain contains an invalid character.\n    #[fail(display = \"invalid character in the domain\")]\n    DomainCharacter,\n\n    /// The base host is missing from the host URL.\n    #[fail(display = \"missing host in the host URL\")]\n    NoBase,\n\n    /// Failed to parse the host URL due to another reason.\n    #[fail(display = \"could not parse host URL\")]\n    Other(#[cause] ParseError),\n}\n"
  },
  {
    "path": "src/main.rs",
    "content": "#[macro_use]\nextern crate clap;\n#[macro_use]\nextern crate derive_builder;\n#[macro_use]\nextern crate failure;\n#[macro_use]\nextern crate lazy_static;\n#[cfg(feature = \"history\")]\n#[macro_use]\nextern crate serde_derive;\n\nmod action;\n#[cfg(feature = \"archive\")]\nmod archive;\nmod client;\nmod cmd;\nmod config;\nmod error;\n#[cfg(feature = \"history\")]\nmod history;\n#[cfg(feature = \"history\")]\nmod history_tool;\nmod host;\nmod progress;\n#[cfg(feature = \"urlshorten\")]\nmod urlshorten;\nmod util;\n\nuse std::process;\n\nuse crate::action::debug::Debug;\nuse crate::action::delete::Delete;\nuse crate::action::download::Download;\nuse crate::action::exists::Exists;\nuse crate::action::generate::Generate;\n#[cfg(feature = \"history\")]\nuse crate::action::history::History;\nuse crate::action::info::Info;\nuse crate::action::params::Params;\nuse crate::action::password::Password;\nuse crate::action::upload::Upload;\nuse crate::action::version::Version;\nuse crate::cmd::{\n    matcher::{MainMatcher, Matcher},\n    Handler,\n};\nuse crate::error::Error;\nuse crate::util::{bin_name, highlight, quit_error, ErrorHints};\n\n/// Application entrypoint.\nfn main() {\n    // Probe for OpenSSL certificates\n    openssl_probe::init_ssl_cert_env_vars();\n\n    // Parse CLI arguments\n    let cmd_handler = Handler::parse();\n\n    // Invoke the proper action\n    if let Err(err) = invoke_action(&cmd_handler) {\n        quit_error(err, ErrorHints::default());\n    };\n}\n\n/// Invoke the proper action based on the CLI input.\n///\n/// If no proper action is selected, the program will quit with an error\n/// message.\nfn invoke_action(handler: &Handler) -> Result<(), Error> {\n    // Match the debug command\n    if handler.debug().is_some() {\n        return Debug::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the delete command\n    if handler.delete().is_some() {\n        return Delete::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the download command\n    if handler.download().is_some() {\n        return Download::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the exists command\n    if handler.exists().is_some() {\n        return Exists::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the generate command\n    if handler.generate().is_some() {\n        return Generate::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the history command\n    #[cfg(feature = \"history\")]\n    {\n        if handler.history().is_some() {\n            return History::new(handler.matches())\n                .invoke()\n                .map_err(|err| err.into());\n        }\n    }\n\n    // Match the info command\n    if handler.info().is_some() {\n        return Info::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the parameters command\n    if handler.params().is_some() {\n        return Params::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the password command\n    if handler.password().is_some() {\n        return Password::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the upload command\n    if handler.upload().is_some() {\n        return Upload::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Match the version command\n    if handler.version().is_some() {\n        return Version::new(handler.matches())\n            .invoke()\n            .map_err(|err| err.into());\n    }\n\n    // Get the main matcher\n    let matcher_main = MainMatcher::with(handler.matches()).unwrap();\n\n    // Print the main info and return\n    if !matcher_main.quiet() {\n        print_main_info();\n    }\n    Ok(())\n}\n\n/// Print the main info, shown when no subcommands were supplied.\npub fn print_main_info() -> ! {\n    // Get the name of the used executable\n    let bin = bin_name();\n\n    // Print the main info\n    println!(\"{} {}\", crate_name!(), crate_version!());\n    println!(\"Usage: {} [FLAGS] <SUBCOMMAND> ...\", bin);\n    println!();\n    println!(crate_description!());\n    println!();\n    println!(\"Missing subcommand. Here are the most used:\");\n    println!(\"    {}\", highlight(&format!(\"{} upload <FILE> ...\", bin)));\n    println!(\"    {}\", highlight(&format!(\"{} download <URL> ...\", bin)));\n    println!();\n    println!(\"To show all subcommands, features and other help:\");\n    println!(\"    {}\", highlight(&format!(\"{} help [SUBCOMMAND]\", bin)));\n    println!();\n    println!(\"The default public Send host is provided by Tim Visee.\");\n    println!(\"Please consider to donate and help keep it running: https://vis.ee/donate\");\n\n    process::exit(1)\n}\n"
  },
  {
    "path": "src/progress.rs",
    "content": "use std::io::{stderr, Stderr};\nuse std::time::Duration;\n\nuse ffsend_api::pipe::ProgressReporter;\nuse pbr::{ProgressBar as Pbr, Units};\n\n/// The refresh rate of the progress bar, in milliseconds.\nconst PROGRESS_BAR_FPS_MILLIS: u64 = 200;\n\n/// A progress bar reporter.\npub struct ProgressBar<'a> {\n    progress_bar: Option<Pbr<Stderr>>,\n    msg_progress: &'a str,\n    msg_finish: &'a str,\n}\n\nimpl<'a> ProgressBar<'a> {\n    /// Construct a new progress bar, with the given messages.\n    pub fn new(msg_progress: &'a str, msg_finish: &'a str) -> ProgressBar<'a> {\n        Self {\n            progress_bar: None,\n            msg_progress,\n            msg_finish,\n        }\n    }\n\n    /// Construct a new progress bar for uploading.\n    pub fn new_upload() -> ProgressBar<'a> {\n        Self::new(\"Encrypt & Upload \", \"Upload complete\")\n    }\n\n    /// Construct a new progress bar for downloading.\n    pub fn new_download() -> ProgressBar<'a> {\n        Self::new(\"Download & Decrypt \", \"Download complete\")\n    }\n}\n\nimpl<'a> ProgressReporter for ProgressBar<'a> {\n    /// Start the progress with the given total.\n    fn start(&mut self, total: u64) {\n        // Initialize the progress bar\n        let mut progress_bar = Pbr::on(stderr(), total);\n        progress_bar.set_max_refresh_rate(Some(Duration::from_millis(PROGRESS_BAR_FPS_MILLIS)));\n        progress_bar.set_units(Units::Bytes);\n        progress_bar.message(self.msg_progress);\n\n        self.progress_bar = Some(progress_bar);\n    }\n\n    /// A progress update.\n    fn progress(&mut self, progress: u64) {\n        self.progress_bar\n            .as_mut()\n            .expect(\"progress bar not yet instantiated, cannot set progress\")\n            .set(progress);\n    }\n\n    /// Finish the progress.\n    fn finish(&mut self) {\n        let progress_bar = self\n            .progress_bar\n            .as_mut()\n            .expect(\"progress bar not yet instantiated\");\n\n        #[cfg(not(target_os = \"windows\"))]\n        progress_bar.finish_print(self.msg_finish);\n        #[cfg(target_os = \"windows\")]\n        {\n            progress_bar.finish_println(self.msg_finish);\n            eprintln!();\n        }\n    }\n}\n"
  },
  {
    "path": "src/urlshorten.rs",
    "content": "//! URL shortening mechanics.\n\nuse ffsend_api::{\n    api::request::{ensure_success, ResponseError},\n    client::Client,\n    reqwest,\n    url::{self, Url},\n};\nuse urlshortener::{\n    providers::{self, Provider},\n    request::{Method, Request},\n};\n\n/// An URL shortening result.\ntype Result<T> = ::std::result::Result<T, Error>;\n\n/// Shorten the given URL.\npub fn shorten(client: &Client, url: &str) -> Result<String> {\n    // TODO: allow selecting other shorteners\n    request(client, providers::request(url, &Provider::IsGd))\n}\n\n/// Shorten the given URL.\npub fn shorten_url(client: &Client, url: &Url) -> Result<Url> {\n    Url::parse(&shorten(client, url.as_str())?).map_err(|err| err.into())\n}\n\n/// Do the request as given, return the response.\nfn request(client: &Client, req: Request) -> Result<String> {\n    // Start the request builder\n    let mut builder = match req.method {\n        Method::Get => client.get(&req.url),\n        Method::Post => client.post(&req.url),\n    };\n\n    // Define the custom user agent\n    if let Some(_agent) = req.user_agent.clone() {\n        // TODO: implement this\n        // builder.header(header::UserAgent::new(agent.0));\n        panic!(\"Custom UserAgent for URL shortener not yet implemented\");\n    }\n\n    // Define the custom content type\n    if let Some(_content_type) = req.content_type {\n        // TODO: implement this\n        // match content_type {\n        //     ContentType::Json => builder.header(header::ContentType::json()),\n        //     ContentType::FormUrlEncoded => {\n        //         builder.header(header::ContentType::form_url_encoded())\n        //     }\n        // };\n        panic!(\"Custom UserAgent for URL shortener not yet implemented\");\n    }\n\n    // Define the custom body\n    if let Some(body) = req.body.clone() {\n        builder = builder.body(body);\n    }\n\n    // Send the request, ensure success\n    let response = builder.send().map_err(Error::Request)?;\n    ensure_success(&response)?;\n\n    // Respond with the body text\n    response.text().map_err(Error::Malformed)\n}\n\n/// An URL shortening error.\n#[derive(Debug, Fail)]\npub enum Error {\n    /// Failed to send the shortening request.\n    #[fail(display = \"failed to send URL shorten request\")]\n    Request(#[cause] reqwest::Error),\n\n    /// The server responded with a bad response.\n    #[fail(display = \"failed to shorten URL, got bad response\")]\n    Response(#[cause] ResponseError),\n\n    /// The server responded with a malformed response.\n    #[fail(display = \"failed to shorten URL, got malformed response\")]\n    Malformed(#[cause] reqwest::Error),\n\n    /// An error occurred while parsing the shortened URL.\n    #[fail(display = \"failed to shorten URL, could not parse URL\")]\n    Url(#[cause] url::ParseError),\n}\n\nimpl From<url::ParseError> for Error {\n    fn from(err: url::ParseError) -> Self {\n        Error::Url(err)\n    }\n}\n\nimpl From<ResponseError> for Error {\n    fn from(err: ResponseError) -> Self {\n        Error::Response(err)\n    }\n}\n"
  },
  {
    "path": "src/util.rs",
    "content": "#[cfg(feature = \"clipboard-crate\")]\nextern crate clip;\n#[cfg(feature = \"clipboard-bin\")]\nextern crate which;\n\nuse std::borrow::Borrow;\nuse std::env::{self, current_exe, var_os};\nuse std::ffi::OsStr;\n#[cfg(feature = \"clipboard\")]\nuse std::fmt;\nuse std::fmt::{Debug, Display};\n#[cfg(feature = \"clipboard-bin\")]\nuse std::io::ErrorKind as IoErrorKind;\nuse std::io::{self, Read};\nuse std::io::{stderr, stdin, Error as IoError, Write};\nuse std::iter;\nuse std::path::Path;\nuse std::path::PathBuf;\nuse std::process::exit;\n#[cfg(feature = \"clipboard-bin\")]\nuse std::process::{Command, Stdio};\n\n#[cfg(feature = \"clipboard-crate\")]\nuse self::clip::{ClipboardContext, ClipboardProvider};\nuse chrono::Duration;\nuse colored::*;\n#[cfg(feature = \"history\")]\nuse directories::ProjectDirs;\nuse failure::{err_msg, Fail};\n#[cfg(feature = \"clipboard-crate\")]\nuse failure::{Compat, Error};\nuse ffsend_api::{\n    api::request::{ensure_success, ResponseError},\n    client::Client,\n    reqwest,\n    url::Url,\n};\nuse fs2::available_space;\nuse rand::distributions::Alphanumeric;\nuse rand::{thread_rng, Rng};\nuse regex::Regex;\nuse rpassword::prompt_password_stderr;\n#[cfg(feature = \"clipboard-bin\")]\nuse which::which;\n\nuse crate::cmd::matcher::MainMatcher;\n\n/// Print a success message.\npub fn print_success(msg: &str) {\n    eprintln!(\"{}\", msg.green());\n}\n\n/// Print the given error in a proper format for the user,\n/// with it's causes.\npub fn print_error<E: Fail>(err: impl Borrow<E>) {\n    // Report each printable error, count them\n    let count = err\n        .borrow()\n        .causes()\n        .map(|err| format!(\"{}\", err))\n        .filter(|err| !err.is_empty())\n        .enumerate()\n        .map(|(i, err)| {\n            if i == 0 {\n                eprintln!(\"{} {}\", highlight_error(\"error:\"), err);\n            } else {\n                eprintln!(\"{} {}\", highlight_error(\"caused by:\"), err);\n            }\n        })\n        .count();\n\n    // Fall back to a basic message\n    if count == 0 {\n        eprintln!(\n            \"{} {}\",\n            highlight_error(\"error:\"),\n            \"an undefined error occurred\"\n        );\n    }\n}\n\n/// Print the given error message in a proper format for the user,\n/// with it's causes.\npub fn print_error_msg<S>(err: S)\nwhere\n    S: AsRef<str> + Display + Debug + Sync + Send + 'static,\n{\n    print_error(err_msg(err).compat());\n}\n\n/// Print a warning.\npub fn print_warning<S>(err: S)\nwhere\n    S: AsRef<str> + Display + Debug + Sync + Send + 'static,\n{\n    eprintln!(\"{} {}\", highlight_warning(\"warning:\"), err);\n}\n\n/// Quit the application regularly.\npub fn quit() -> ! {\n    exit(0);\n}\n\n/// Quit the application with an error code,\n/// and print the given error.\npub fn quit_error<E: Fail>(err: E, hints: impl Borrow<ErrorHints>) -> ! {\n    // Print the error\n    print_error(err);\n\n    // Print error hints\n    hints.borrow().print();\n\n    // Quit\n    exit(1);\n}\n\n/// Quit the application with an error code,\n/// and print the given error message.\npub fn quit_error_msg<S>(err: S, hints: impl Borrow<ErrorHints>) -> !\nwhere\n    S: AsRef<str> + Display + Debug + Sync + Send + 'static,\n{\n    quit_error(err_msg(err).compat(), hints);\n}\n\n/// The error hint configuration.\n#[derive(Clone, Builder)]\n#[builder(default)]\npub struct ErrorHints {\n    /// Show about specifying an API version.\n    api: bool,\n\n    /// A list of info messages to print along with the error.\n    info: Vec<String>,\n\n    /// Show about the name option.\n    name: bool,\n\n    /// Show about the password option.\n    password: bool,\n\n    /// Show about the owner option.\n    owner: bool,\n\n    /// Show about the history flag.\n    #[cfg(feature = \"history\")]\n    history: bool,\n\n    /// Show about the force flag.\n    force: bool,\n\n    /// Show about the verbose flag.\n    verbose: bool,\n\n    /// Show about the help flag.\n    help: bool,\n}\n\nimpl ErrorHints {\n    /// Check whether any hint should be printed.\n    pub fn any(&self) -> bool {\n        // Determine the result\n        #[allow(unused_mut)]\n        let mut result =\n            self.name || self.password || self.owner || self.force || self.verbose || self.help;\n\n        // Factor in the history hint when enabled\n        #[cfg(feature = \"history\")]\n        {\n            result = result || self.history;\n        }\n\n        result\n    }\n\n    /// Print the error hints.\n    pub fn print(&self) {\n        // Print info messages\n        for msg in &self.info {\n            eprintln!(\"{} {}\", highlight_info(\"info:\"), msg);\n        }\n\n        // Stop if nothing should be printed\n        if !self.any() {\n            return;\n        }\n\n        eprint!(\"\\n\");\n\n        // Print hints\n        if self.api {\n            eprintln!(\n                \"Use '{}' to select a server API version\",\n                highlight(\"--api <VERSION>\")\n            );\n        }\n        if self.name {\n            eprintln!(\n                \"Use '{}' to specify a file name\",\n                highlight(\"--name <NAME>\")\n            );\n        }\n        if self.password {\n            eprintln!(\n                \"Use '{}' to specify a password\",\n                highlight(\"--password <PASSWORD>\")\n            );\n        }\n        if self.owner {\n            eprintln!(\n                \"Use '{}' to specify an owner token\",\n                highlight(\"--owner <TOKEN>\")\n            );\n        }\n        #[cfg(feature = \"history\")]\n        {\n            if self.history {\n                eprintln!(\n                    \"Use '{}' to specify a history file\",\n                    highlight(\"--history <FILE>\")\n                );\n            }\n        }\n        if self.force {\n            eprintln!(\"Use '{}' to force\", highlight(\"--force\"));\n        }\n        if self.verbose {\n            eprintln!(\"For detailed errors try '{}'\", highlight(\"--verbose\"));\n        }\n        if self.help {\n            eprintln!(\"For more information try '{}'\", highlight(\"--help\"));\n        }\n\n        // Flush\n        let _ = stderr().flush();\n    }\n}\n\nimpl Default for ErrorHints {\n    fn default() -> Self {\n        ErrorHints {\n            api: false,\n            info: Vec::new(),\n            name: false,\n            password: false,\n            owner: false,\n            #[cfg(feature = \"history\")]\n            history: false,\n            force: false,\n            verbose: true,\n            help: true,\n        }\n    }\n}\n\nimpl ErrorHintsBuilder {\n    /// Add a single info entry.\n    pub fn add_info(mut self, info: String) -> Self {\n        // Initialize the info list\n        if self.info.is_none() {\n            self.info = Some(Vec::new());\n        }\n\n        // Add the item to the info list\n        if let Some(ref mut list) = self.info {\n            list.push(info);\n        }\n\n        self\n    }\n}\n\n/// Highlight the given text with a color.\npub fn highlight(msg: &str) -> ColoredString {\n    msg.yellow()\n}\n\n/// Highlight the given text with an error color.\npub fn highlight_error(msg: &str) -> ColoredString {\n    msg.red().bold()\n}\n\n/// Highlight the given text with an warning color.\npub fn highlight_warning(msg: &str) -> ColoredString {\n    highlight(msg).bold()\n}\n\n/// Highlight the given text with an info color\npub fn highlight_info(msg: &str) -> ColoredString {\n    msg.cyan()\n}\n\n/// Open the given URL in the users default browser.\n/// The browsers exit status is returned.\npub fn open_url(url: impl Borrow<Url>) -> Result<(), IoError> {\n    open_path(url.borrow().as_str())\n}\n\n/// Open the given path or URL using the program configured on the system.\n/// The program exit status is returned.\npub fn open_path(path: &str) -> Result<(), IoError> {\n    open::that(path)\n}\n\n/// Set the clipboard of the user to the given `content` string.\n#[cfg(feature = \"clipboard\")]\npub fn set_clipboard(content: String) -> Result<(), ClipboardError> {\n    ClipboardType::select().set(content)\n}\n\n/// Clipboard management enum.\n///\n/// Defines which method of setting the clipboard is used.\n/// Invoke `ClipboardType::select()` to select the best variant to use determined at runtime.\n///\n/// Usually, the `Native` variant is used. However, on Linux system a different variant will be\n/// selected which will call a system binary to set the clipboard. This must be done because the\n/// native clipboard interface only has a lifetime of the application. This means that the\n/// clipboard is instantly cleared as soon as this application quits, which is always immediately.\n/// This limitation is due to security reasons as defined by X11. The alternative binaries we set\n/// the clipboard with spawn a daemon in the background to keep the clipboard alive until it's\n/// flushed.\n#[cfg(feature = \"clipboard\")]\n#[derive(Clone, Eq, PartialEq)]\npub enum ClipboardType {\n    /// Native operating system clipboard.\n    #[cfg(feature = \"clipboard-crate\")]\n    Native,\n\n    /// Manage clipboard through `xclip` on Linux.\n    ///\n    /// May contain a binary path if specified at compile time through the `XCLIP_PATH` variable.\n    #[cfg(feature = \"clipboard-bin\")]\n    Xclip(Option<String>),\n\n    /// Manage clipboard through `xsel` on Linux.\n    ///\n    /// May contain a binary path if specified at compile time through the `XSEL_PATH` variable.\n    #[cfg(feature = \"clipboard-bin\")]\n    Xsel(Option<String>),\n}\n\n#[cfg(feature = \"clipboard\")]\nimpl ClipboardType {\n    /// Select the clipboard type to use, depending on the runtime system.\n    pub fn select() -> Self {\n        #[cfg(feature = \"clipboard-crate\")]\n        {\n            ClipboardType::Native\n        }\n\n        #[cfg(feature = \"clipboard-bin\")]\n        {\n            if let Some(path) = option_env!(\"XCLIP_PATH\") {\n                ClipboardType::Xclip(Some(path.to_owned()))\n            } else if let Some(path) = option_env!(\"XSEL_PATH\") {\n                ClipboardType::Xsel(Some(path.to_owned()))\n            } else if which(\"xclip\").is_ok() {\n                ClipboardType::Xclip(None)\n            } else if which(\"xsel\").is_ok() {\n                ClipboardType::Xsel(None)\n            } else {\n                // TODO: should we error here instead, as no clipboard binary was found?\n                ClipboardType::Xclip(None)\n            }\n        }\n    }\n\n    /// Set clipboard contents through the selected clipboard type.\n    pub fn set(&self, content: String) -> Result<(), ClipboardError> {\n        match self {\n            #[cfg(feature = \"clipboard-crate\")]\n            ClipboardType::Native => Self::native_set(content),\n            #[cfg(feature = \"clipboard-bin\")]\n            ClipboardType::Xclip(path) => Self::xclip_set(path.clone(), &content),\n            #[cfg(feature = \"clipboard-bin\")]\n            ClipboardType::Xsel(path) => Self::xsel_set(path.clone(), &content),\n        }\n    }\n\n    /// Set the clipboard through a native interface.\n    ///\n    /// This is used on non-Linux systems.\n    #[cfg(feature = \"clipboard-crate\")]\n    fn native_set(content: String) -> Result<(), ClipboardError> {\n        ClipboardProvider::new()\n            .and_then(|mut context: ClipboardContext| context.set_contents(content))\n            .map_err(|err| format_err!(\"{}\", err).compat())\n            .map_err(ClipboardError::Native)\n    }\n\n    #[cfg(feature = \"clipboard-bin\")]\n    fn xclip_set(path: Option<String>, content: &str) -> Result<(), ClipboardError> {\n        Self::sys_cmd_set(\n            \"xclip\",\n            Command::new(path.unwrap_or_else(|| \"xclip\".into()))\n                .arg(\"-sel\")\n                .arg(\"clip\"),\n            content,\n        )\n    }\n\n    #[cfg(feature = \"clipboard-bin\")]\n    fn xsel_set(path: Option<String>, content: &str) -> Result<(), ClipboardError> {\n        Self::sys_cmd_set(\n            \"xsel\",\n            Command::new(path.unwrap_or_else(|| \"xsel\".into())).arg(\"--clipboard\"),\n            content,\n        )\n    }\n\n    #[cfg(feature = \"clipboard-bin\")]\n    fn sys_cmd_set(\n        bin: &'static str,\n        command: &mut Command,\n        content: &str,\n    ) -> Result<(), ClipboardError> {\n        // Spawn the command process for setting the clipboard\n        let mut process = match command.stdin(Stdio::piped()).stdout(Stdio::null()).spawn() {\n            Ok(process) => process,\n            Err(err) => {\n                return Err(match err.kind() {\n                    IoErrorKind::NotFound => ClipboardError::NoBinary,\n                    _ => ClipboardError::BinaryIo(bin, err),\n                });\n            }\n        };\n\n        // Write the contents to the xclip process\n        process\n            .stdin\n            .as_mut()\n            .unwrap()\n            .write_all(content.as_bytes())\n            .map_err(|err| ClipboardError::BinaryIo(bin, err))?;\n\n        // Wait for xclip to exit\n        let status = process\n            .wait()\n            .map_err(|err| ClipboardError::BinaryIo(bin, err))?;\n        if !status.success() {\n            return Err(ClipboardError::BinaryStatus(\n                bin,\n                status.code().unwrap_or(0),\n            ));\n        }\n\n        Ok(())\n    }\n}\n\n#[cfg(feature = \"clipboard\")]\nimpl fmt::Display for ClipboardType {\n    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {\n        match self {\n            #[cfg(feature = \"clipboard-crate\")]\n            ClipboardType::Native => write!(f, \"native\"),\n            #[cfg(feature = \"clipboard-bin\")]\n            ClipboardType::Xclip(path) => match path {\n                None => write!(f, \"xclip\"),\n                Some(path) => write!(f, \"xclip ({})\", path),\n            },\n            #[cfg(feature = \"clipboard-bin\")]\n            ClipboardType::Xsel(path) => match path {\n                None => write!(f, \"xsel\"),\n                Some(path) => write!(f, \"xsel ({})\", path),\n            },\n        }\n    }\n}\n\n#[cfg(feature = \"clipboard\")]\n#[derive(Debug, Fail)]\npub enum ClipboardError {\n    /// A generic error occurred while setting the clipboard contents.\n    ///\n    /// This is for non-Linux systems, using a native clipboard interface.\n    #[cfg(feature = \"clipboard-crate\")]\n    #[fail(display = \"failed to access clipboard\")]\n    Native(#[cause] Compat<Error>),\n\n    /// The `xclip` or `xsel` binary could not be found on the system, required for clipboard support.\n    #[cfg(feature = \"clipboard-bin\")]\n    #[fail(display = \"failed to access clipboard, xclip or xsel is not installed\")]\n    NoBinary,\n\n    /// An error occurred while using `xclip` or `xsel` to set the clipboard contents.\n    /// This problem probably occurred when starting, or while piping the clipboard contents to\n    /// the process.\n    #[cfg(feature = \"clipboard-bin\")]\n    #[fail(display = \"failed to access clipboard using {}\", _0)]\n    BinaryIo(&'static str, #[cause] IoError),\n\n    /// `xclip` or `xsel` unexpectedly exited with a non-successful status code.\n    #[cfg(feature = \"clipboard-bin\")]\n    #[fail(\n        display = \"failed to use clipboard, {} exited with status code {}\",\n        _0, _1\n    )]\n    BinaryStatus(&'static str, i32),\n}\n\n/// Check for an empty password in the given `password`.\n/// If the password is empty the program will quit with an error unless\n/// forced.\n// TODO: move this to a better module\npub fn check_empty_password(password: &str, matcher_main: &MainMatcher) {\n    if !matcher_main.force() && password.is_empty() {\n        quit_error_msg(\n            \"an empty password is not supported by the web interface\",\n            ErrorHintsBuilder::default()\n                .force(true)\n                .verbose(false)\n                .build()\n                .unwrap(),\n        )\n    }\n}\n\n/// Prompt the user to enter a password.\n///\n/// If `empty` is `false`, empty passwords aren't allowed unless forced.\npub fn prompt_password(main_matcher: &MainMatcher, optional: bool) -> Option<String> {\n    // Quit with an error if we may not interact\n    if !optional && main_matcher.no_interact() {\n        quit_error_msg(\n            \"missing password, must be specified in no-interact mode\",\n            ErrorHintsBuilder::default()\n                .password(true)\n                .verbose(false)\n                .build()\n                .unwrap(),\n        );\n    }\n\n    // Prompt for the password\n    let prompt = if optional {\n        \"Password (optional): \"\n    } else {\n        \"Password: \"\n    };\n    match prompt_password_stderr(prompt) {\n        // If optional and nothing is entered, regard it as not defined\n        Ok(password) => {\n            if password.is_empty() && optional {\n                None\n            } else {\n                Some(password)\n            }\n        }\n\n        // On input error, propagate the error or don't use a password if optional\n        Err(err) => {\n            if !optional {\n                quit_error(\n                    err.context(\"failed to read password from password prompt\"),\n                    ErrorHints::default(),\n                )\n            } else {\n                None\n            }\n        }\n    }\n}\n\n/// Get a password if required.\n/// This method will ensure a password is set (or not) in the given `password`\n/// parameter, as defined by `needs`.\n/// If a password is needed, it may optionally be entered if `option` is set to true.\n///\n/// This method will prompt the user for a password, if one is required but\n/// wasn't set. An ignore message will be shown if it was not required while it\n/// was set.\n///\n/// Returns true if a password is now set, false if not.\npub fn ensure_password(\n    password: &mut Option<String>,\n    needs: bool,\n    main_matcher: &MainMatcher,\n    optional: bool,\n) -> bool {\n    // Return if we're fine, ignore if set but we don't need it\n    if password.is_some() == needs {\n        return needs;\n    }\n    if !needs {\n        // Notify the user a set password is ignored\n        if password.is_some() {\n            println!(\"Ignoring password, it is not required\");\n            *password = None;\n        }\n        return false;\n    }\n\n    // Check whether we allow interaction\n    let interact = !main_matcher.no_interact();\n\n    loop {\n        // Prompt for an owner token if not set yet\n        if password.is_none() {\n            // Do not ask for a token if optional when non-interactive or forced\n            if optional && (!interact || main_matcher.force()) {\n                return false;\n            }\n\n            // Ask for the password\n            *password = prompt_password(main_matcher, optional);\n        }\n\n        // The token must not be empty, unless it's optional\n        let empty = password.is_none();\n        if empty && !optional {\n            eprintln!(\n                \"No password given, which is required. Use {} to cancel.\",\n                highlight(\"[CTRL+C]\"),\n            );\n        } else {\n            return !empty;\n        }\n    }\n}\n\n/// Prompt the user to enter some value.\n/// The prompt that is shown should be passed to `msg`,\n/// excluding the `:` suffix.\npub fn prompt(msg: &str, main_matcher: &MainMatcher) -> String {\n    // Quit with an error if we may not interact\n    if main_matcher.no_interact() {\n        quit_error_msg(\n            format!(\n                \"could not prompt for '{}' in no-interact mode, maybe specify it\",\n                msg,\n            ),\n            ErrorHints::default(),\n        );\n    }\n\n    // Show the prompt\n    eprint!(\"{}: \", msg);\n    let _ = stderr().flush();\n\n    // Get the input\n    let mut input = String::new();\n    if let Err(err) = stdin().read_line(&mut input) {\n        quit_error(\n            err.context(\"failed to read input from prompt\"),\n            ErrorHints::default(),\n        );\n    }\n\n    // Trim and return\n    input.trim().to_owned()\n}\n\n/// Prompt the user for a question, allowing a yes or now answer.\n/// True is returned if yes was answered, false if no.\n///\n/// A default may be given, which is chosen if no-interact mode is\n/// enabled, or if enter was pressed by the user without entering anything.\npub fn prompt_yes(msg: &str, def: Option<bool>, main_matcher: &MainMatcher) -> bool {\n    // Define the available options string\n    let options = format!(\n        \"[{}/{}]\",\n        match def {\n            Some(def) if def => \"Y\",\n            _ => \"y\",\n        },\n        match def {\n            Some(def) if !def => \"N\",\n            _ => \"n\",\n        }\n    );\n\n    // Assume yes\n    if main_matcher.assume_yes() {\n        eprintln!(\"{} {}: yes\", msg, options);\n        return true;\n    }\n\n    // Autoselect if in no-interact mode\n    if main_matcher.no_interact() {\n        if let Some(def) = def {\n            eprintln!(\"{} {}: {}\", msg, options, if def { \"yes\" } else { \"no\" });\n            return def;\n        } else {\n            quit_error_msg(\n                format!(\n                    \"could not prompt question '{}' in no-interact mode, maybe specify it\",\n                    msg,\n                ),\n                ErrorHints::default(),\n            );\n        }\n    }\n\n    // Get the user input\n    let answer = prompt(&format!(\"{} {}\", msg, options), main_matcher);\n\n    // Assume the default if the answer is empty\n    if answer.is_empty() && def.is_some() {\n        return def.unwrap();\n    }\n\n    // Derive a boolean and return\n    match derive_bool(&answer) {\n        Some(answer) => answer,\n        None => prompt_yes(msg, def, main_matcher),\n    }\n}\n\n/// Try to derive true or false (yes or no) from the given input.\n/// None is returned if no boolean could be derived accurately.\nfn derive_bool(input: &str) -> Option<bool> {\n    // Process the input\n    let input = input.trim().to_lowercase();\n\n    // Handle short or incomplete answers\n    match input.as_str() {\n        \"y\" | \"ye\" | \"t\" | \"1\" => return Some(true),\n        \"n\" | \"f\" | \"0\" => return Some(false),\n        _ => {}\n    }\n\n    // Handle complete answers with any suffix\n    if input.starts_with(\"yes\") || input.starts_with(\"true\") {\n        return Some(true);\n    }\n    if input.starts_with(\"no\") || input.starts_with(\"false\") {\n        return Some(false);\n    }\n\n    // The answer could not be determined, return none\n    None\n}\n\n/// Prompt the user to enter an owner token.\npub fn prompt_owner_token(main_matcher: &MainMatcher, optional: bool) -> String {\n    prompt(\n        if optional {\n            \"Owner token (optional)\"\n        } else {\n            \"Owner token\"\n        },\n        main_matcher,\n    )\n}\n\n/// Get the owner token.\n/// This method will ensure an owner token is set in the given `token`\n/// parameter.\n///\n/// This method will prompt the user for the token, if it wasn't set.\n///\n/// Returns if an owner token was set.\n/// If `optional` is false, this always returns true.\n///\n/// If in non-interactive or force mode, the user will not be prompted for a token if `optional` is\n/// set to true.\npub fn ensure_owner_token(\n    token: &mut Option<String>,\n    main_matcher: &MainMatcher,\n    optional: bool,\n) -> bool {\n    // Check whether we allow interaction\n    let interact = !main_matcher.no_interact();\n\n    // Notify that an owner token is required\n    if interact && token.is_none() {\n        if optional {\n            println!(\"The file owner token is recommended for authentication.\");\n        } else {\n            println!(\"The file owner token is required for authentication.\");\n        }\n    }\n\n    loop {\n        // Prompt for an owner token if not set yet\n        if token.is_none() {\n            // Do not ask for a token if optional when non-interactive or forced\n            if optional && (!interact || main_matcher.force()) {\n                return false;\n            }\n\n            // Ask for the token, or quit with an error if non-interactive\n            if interact {\n                *token = Some(prompt_owner_token(main_matcher, optional));\n            } else {\n                quit_error_msg(\n                    \"missing owner token, must be specified in no-interact mode\",\n                    ErrorHintsBuilder::default()\n                        .owner(true)\n                        .verbose(false)\n                        .build()\n                        .unwrap(),\n                );\n            }\n        }\n\n        // The token must not be empty, unless it's optional\n        let empty = token.as_ref().unwrap().is_empty();\n        if empty {\n            *token = None;\n        }\n        if empty && !optional {\n            eprintln!(\n                \"Empty owner token given, which is invalid. Use {} to cancel.\",\n                highlight(\"[CTRL+C]\"),\n            );\n        } else {\n            return !empty;\n        }\n    }\n}\n\n/// Format the given number of bytes readable for humans.\npub fn format_bytes(bytes: u64) -> String {\n    let bytes = bytes as f64;\n    let kb = 1024f64;\n    match bytes {\n        bytes if bytes >= kb.powf(4_f64) => format!(\"{:.*} TiB\", 2, bytes / kb.powf(4_f64)),\n        bytes if bytes >= kb.powf(3_f64) => format!(\"{:.*} GiB\", 2, bytes / kb.powf(3_f64)),\n        bytes if bytes >= kb.powf(2_f64) => format!(\"{:.*} MiB\", 2, bytes / kb.powf(2_f64)),\n        bytes if bytes >= kb => format!(\"{:.*} KiB\", 2, bytes / kb),\n        _ => format!(\"{:.*} B\", 0, bytes),\n    }\n}\n\n/// Parse the given duration string from human readable format into seconds.\n/// This method parses a string of time components to represent the given duration.\n///\n/// The following time units are used:\n/// - `w`: weeks\n/// - `d`: days\n/// - `h`: hours\n/// - `m`: minutes\n/// - `s`: seconds\n/// The following time strings can be parsed:\n/// - `8w6d`\n/// - `23h14m`\n/// - `9m55s`\n/// - `1s1s1s1s1s`\npub fn parse_duration(duration: &str) -> Result<usize, ParseDurationError> {\n    // Build a regex to grab time parts\n    let re = Regex::new(r\"(?i)([0-9]+)(([a-z]|\\s*$))\")\n        .expect(\"failed to compile duration parsing regex\");\n\n    // We must find any match\n    if re.find(duration).is_none() {\n        return Err(ParseDurationError::Empty);\n    }\n\n    // Parse each time part, sum it's seconds\n    let mut seconds = 0;\n    for capture in re.captures_iter(duration) {\n        // Parse time value and modifier\n        let number = capture[1]\n            .parse::<usize>()\n            .map_err(ParseDurationError::InvalidValue)?;\n        let modifier = capture[2].trim().to_lowercase();\n\n        // Multiply and sum seconds by modifier\n        seconds += match modifier.as_str() {\n            \"\" | \"s\" => number,\n            \"m\" => number * 60,\n            \"h\" => number * 60 * 60,\n            \"d\" => number * 60 * 60 * 24,\n            \"w\" => number * 60 * 60 * 24 * 7,\n            m => return Err(ParseDurationError::UnknownIdentifier(m.into())),\n        };\n    }\n\n    Ok(seconds)\n}\n\n/// Represents a duration parsing error.\n#[derive(Debug, Fail)]\npub enum ParseDurationError {\n    /// The given duration string did not contain any duration part.\n    #[fail(display = \"given string did not contain any duration part\")]\n    Empty,\n\n    /// A numeric value was invalid.\n    #[fail(display = \"duration part has invalid numeric value\")]\n    InvalidValue(std::num::ParseIntError),\n\n    /// The given duration string contained an invalid duration modifier.\n    #[fail(display = \"duration part has unknown time identifier '{}'\", _0)]\n    UnknownIdentifier(String),\n}\n\n/// Format the given duration in a human readable format.\n/// This method builds a string of time components to represent\n/// the given duration.\n///\n/// The following time units are used:\n/// - `w`: weeks\n/// - `d`: days\n/// - `h`: hours\n/// - `m`: minutes\n/// - `s`: seconds\n///\n/// Only the two most significant units are returned.\n/// If the duration is zero seconds or less `now` is returned.\n///\n/// The following time strings may be produced:\n/// - `8w6d`\n/// - `23h14m`\n/// - `9m55s`\n/// - `1s`\n/// - `now`\npub fn format_duration(duration: impl Borrow<Duration>) -> String {\n    // Get the total number of seconds, return immediately if zero or less\n    let mut secs = duration.borrow().num_seconds();\n    if secs <= 0 {\n        return \"now\".into();\n    }\n\n    // Build a list of time units, define a list for time components\n    let mut components = Vec::new();\n    let units = [\n        (60 * 60 * 24 * 7, \"w\"),\n        (60 * 60 * 24, \"d\"),\n        (60 * 60, \"h\"),\n        (60, \"m\"),\n        (1, \"s\"),\n    ];\n\n    // Fill the list of time components based on the units which fit\n    for unit in &units {\n        if secs >= unit.0 {\n            components.push(format!(\"{}{}\", secs / unit.0, unit.1));\n            secs %= unit.0;\n        }\n    }\n\n    // Show only the two most significant components and join them in a string\n    components.truncate(2);\n    components.join(\"\")\n}\n\n/// Format the given boolean, as `yes` or `no`.\npub fn format_bool(b: bool) -> &'static str {\n    if b {\n        \"yes\"\n    } else {\n        \"no\"\n    }\n}\n\n/// Get the name of the executable that was invoked.\n///\n/// When a symbolic or hard link is used, the name of the link is returned.\n///\n/// This attempts to obtain the binary name in the following order:\n/// - name in first item of program arguments via `std::env::args`\n/// - current executable name via `std::env::current_exe`\n/// - crate name\npub fn bin_name() -> String {\n    env::args_os()\n        .next()\n        .filter(|path| !path.is_empty())\n        .map(PathBuf::from)\n        .or_else(|| current_exe().ok())\n        .and_then(|p| p.file_name().map(|n| n.to_owned()))\n        .and_then(|n| n.into_string().ok())\n        .unwrap_or_else(|| crate_name!().into())\n}\n\n/// Ensure that there is enough free disk space available at the given `path`,\n/// to store a file with the given `size`.\n///\n/// If an error occurred while querying the file system,\n/// the error is reported to the user and the method returns.\n///\n/// If there is not enough disk space available,\n/// an error is reported and the program will quit.\npub fn ensure_enough_space<P: AsRef<Path>>(path: P, size: u64) {\n    // Get the available space at this path\n    let space = match available_space(path) {\n        Ok(space) => space,\n        Err(err) => {\n            print_error(err.context(\"failed to check available space on disk, ignoring\"));\n            return;\n        }\n    };\n\n    // Return if enough disk space is available\n    if space >= size {\n        return;\n    }\n\n    // Create an info message giving details about the required space\n    let info = format!(\n        \"{} of space required, but only {} is available\",\n        format_bytes(size),\n        format_bytes(space),\n    );\n\n    // Print an descriptive error and quit\n    quit_error(\n        err_msg(\"not enough disk space available in the target directory\")\n            .context(\"failed to download file\"),\n        ErrorHintsBuilder::default()\n            .add_info(info)\n            .force(true)\n            .verbose(false)\n            .build()\n            .unwrap(),\n    );\n}\n\n/// Get the project directories instance for this application.\n/// This may be used to determine the project, cache, configuration, data and\n/// some other directory paths.\n#[cfg(feature = \"history\")]\npub fn app_project_dirs() -> ProjectDirs {\n    ProjectDirs::from(\"\", \"\", crate_name!())\n        .expect(\"failed to determine location of project directories\")\n}\n\n/// Get the default path to use for the history file.\n#[cfg(feature = \"history\")]\npub fn app_history_file_path() -> PathBuf {\n    app_project_dirs().cache_dir().join(\"history.toml\")\n}\n\n/// Get the default path to use for the history file, as a string.\n#[cfg(feature = \"history\")]\npub fn app_history_file_path_string() -> String {\n    app_history_file_path().to_str().unwrap().to_owned()\n}\n\n/// Check whether an environment variable with the given key is present in the context of the\n/// current process. The environment variable doesn't have to hold any specific value.\n/// Returns `true` if present, `false` if not.\npub fn env_var_present(key: impl AsRef<OsStr>) -> bool {\n    var_os(key).is_some()\n}\n\n/// Get a list of all features that were enabled during compilation.\npub fn features_list() -> Vec<&'static str> {\n    // Build the list\n    #[allow(unused_mut)]\n    let mut features = Vec::new();\n\n    // Add each feature\n    #[cfg(feature = \"archive\")]\n    features.push(\"archive\");\n    #[cfg(feature = \"clipboard\")]\n    features.push(\"clipboard\");\n    #[cfg(feature = \"clipboard-bin\")]\n    features.push(\"clipboard-bin\");\n    #[cfg(feature = \"clipboard-crate\")]\n    features.push(\"clipboard-crate\");\n    #[cfg(feature = \"history\")]\n    features.push(\"history\");\n    #[cfg(feature = \"qrcode\")]\n    features.push(\"qrcode\");\n    #[cfg(feature = \"urlshorten\")]\n    features.push(\"urlshorten\");\n    #[cfg(feature = \"infer-command\")]\n    features.push(\"infer-command\");\n    #[cfg(feature = \"no-qcolor\")]\n    features.push(\"no-color\");\n    #[cfg(feature = \"send2\")]\n    features.push(\"send2\");\n    #[cfg(feature = \"send3\")]\n    features.push(\"send3\");\n    #[cfg(feature = \"crypto-ring\")]\n    features.push(\"crypto-ring\");\n    #[cfg(feature = \"crypto-openssl\")]\n    features.push(\"crypto-openssl\");\n\n    features\n}\n\n/// Get a list of supported API versions.\npub fn api_version_list() -> Vec<&'static str> {\n    // Build the list\n    #[allow(unused_mut)]\n    let mut versions = Vec::new();\n\n    // Add each feature\n    #[cfg(feature = \"send2\")]\n    versions.push(\"v2\");\n    #[cfg(feature = \"send3\")]\n    versions.push(\"v3\");\n\n    versions\n}\n\n/// Follow redirects on the given URL, and return the final full URL.\n///\n/// This is used to obtain share URLs from shortened links.\n///\n// TODO: extract this into module\npub fn follow_url(client: &Client, url: &Url) -> Result<Url, FollowError> {\n    // Send the request, follow the URL, ensure success\n    let response = client\n        .get(url.as_str())\n        .send()\n        .map_err(FollowError::Request)?;\n    ensure_success(&response)?;\n\n    // Obtain the final URL\n    Ok(response.url().clone())\n}\n\n/// URL following error.\n#[derive(Debug, Fail)]\npub enum FollowError {\n    /// Failed to send the shortening request.\n    #[fail(display = \"failed to send URL follow request\")]\n    Request(#[cause] reqwest::Error),\n\n    /// The server responded with a bad response.\n    #[fail(display = \"failed to shorten URL, got bad response\")]\n    Response(#[cause] ResponseError),\n}\n\nimpl From<ResponseError> for FollowError {\n    fn from(err: ResponseError) -> Self {\n        FollowError::Response(err)\n    }\n}\n\n/// Generate a random alphanumeric string with the given length.\npub fn rand_alphanum_string(len: usize) -> String {\n    let mut rng = thread_rng();\n    iter::repeat(())\n        .map(|()| rng.sample(Alphanumeric) as char)\n        .take(len)\n        .collect()\n}\n\n/// Read file from stdin.\npub fn stdin_read_file(prompt: bool) -> Result<Vec<u8>, StdinErr> {\n    if prompt {\n        #[cfg(not(windows))]\n        eprintln!(\"Enter input. Use [CTRL+D] to stop:\");\n        #[cfg(windows)]\n        eprintln!(\"Enter input. Use [CTRL+Z] to stop:\");\n    }\n\n    let mut data = vec![];\n    io::stdin()\n        .lock()\n        .read_to_end(&mut data)\n        .map_err(StdinErr::Stdin)?;\n    Ok(data)\n}\n\n/// URL following error.\n#[derive(Debug, Fail)]\npub enum StdinErr {\n    #[fail(display = \"failed to read from stdin\")]\n    Stdin(#[cause] io::Error),\n}\n"
  }
]