├── .editorconfig ├── .travis.yml ├── .pre-commit-config.yaml ├── LICENSE.md ├── README.md └── bin └── 0x0 /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: bionic 2 | language: generic 3 | 4 | install: 5 | - pyenv global 3.7.1 6 | - pip3 install --user pre-commit 7 | 8 | script: 9 | - $HOME/.local/bin/pre-commit run --all-files 10 | - shellcheck --color bin/0x0 11 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v3.3.0 4 | hooks: 5 | - id: fix-byte-order-marker 6 | - id: end-of-file-fixer 7 | - id: trailing-whitespace 8 | 9 | - id: mixed-line-ending 10 | args: [--fix=lf] 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright © 2018-2019 Hugo Locurcio and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 0x0 2 | 3 | **Upload files from local or remote locations to [0x0.st](https://0x0.st/).** 4 | 5 | ## Installation 6 | 7 | The only dependency is [curl](https://curl.haxx.se/), which can be installed 8 | from your distribution's repositories. 9 | 10 | ### Using [basher](https://github.com/basherpm/basher) 11 | 12 | ```bash 13 | basher install Calinou/0x0 14 | ``` 15 | 16 | Using this installation method, `0x0` will be immediately available in your PATH. 17 | 18 | ### Manual installation 19 | 20 | ```bash 21 | # Download the script 22 | curl -LO https://raw.githubusercontent.com/Calinou/0x0/master/bin/0x0 23 | 24 | # Make the script executable 25 | chmod +x 0x0 26 | 27 | # Move the script to a location in your PATH 28 | sudo mv 0x0 /usr/local/bin 29 | ``` 30 | 31 | ## Usage 32 | 33 | ```bash 34 | # Upload a local file 35 | 0x0 some_file.png 36 | 37 | # Upload from an URL (the file won't be fetched locally). 38 | # The URL must start with `http://` or `https://`. 39 | 0x0 http://example.com 40 | 41 | # Upload from standard input. 42 | # Example usage with a pipe: `tail some_file | 0x0 -` 43 | 0x0 - 44 | ``` 45 | 46 | If the upload is successful, the file URL will be printed to standard output. 47 | 48 | ## License 49 | 50 | Copyright © 2018-2019 Hugo Locurcio and contributors 51 | 52 | Unless otherwise specified, files in this repository are licensed under 53 | the MIT license; see [LICENSE.md](LICENSE.md) for more information. 54 | -------------------------------------------------------------------------------- /bin/0x0: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Copyright © 2018-2019 Hugo Locurcio and contributors 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | set -euo pipefail 24 | IFS=$'\n\t' 25 | 26 | API_ENDPOINT=https://0x0.st/ 27 | EXPIRES=0 28 | INPUT_ARG="" 29 | MIMETYPE="" 30 | SECRET=true 31 | VERBOSE=false 32 | 33 | if [[ -t 1 ]]; then 34 | # stdout is a TTY, enable colors 35 | STYLE_COMMAND="\033[0;97m" 36 | STYLE_ARG="\033[0;96m" 37 | STYLE_ERROR="\033[91m" 38 | STYLE_BOLD="\033[1m" 39 | STYLE_NORMAL="\033[22m" 40 | STYLE_RESET="\033[0m" 41 | else 42 | # stdout is not a TTY, disable colors 43 | STYLE_COMMAND="" 44 | STYLE_ARG="" 45 | STYLE_ERROR="" 46 | STYLE_BOLD="" 47 | STYLE_NORMAL="" 48 | STYLE_RESET="" 49 | fi 50 | 51 | # Prints an error message to stderr 52 | print_error() { 53 | echo -e "${STYLE_ERROR}${STYLE_BOLD}Error:${STYLE_NORMAL} $1${STYLE_RESET}" >&2 54 | exit 1 55 | } 56 | 57 | print_help() { 58 | base="${0##*/}" 59 | echo -e "${STYLE_BOLD}0x0, a wrapper script for ${API_ENDPOINT}${STYLE_RESET}\n" 60 | echo -e "Usage: ${base} [options] \n" 61 | echo -e "Options:" 62 | echo -e " -e | --expires ${STYLE_ARG}${STYLE_RESET} Set an expiration on the file" 63 | echo -e " 'number' is the number of hours from now or" 64 | echo -e " a timestamp in epoch milliseconds." 65 | echo -e " -m | --mimetype ${STYLE_ARG}${STYLE_RESET} Force a mime-type to the uploaded content" 66 | echo -e " example: -m text/plain" 67 | echo -e " -n | --no-secret Use a short, easy-to-guess URL" 68 | echo -e " -v | --verbose Also return relevant headers from response" 69 | echo -e " Outputs x-expires and x-token headers if present" 70 | echo -e "Examples:" 71 | echo -e " Upload a file:" 72 | echo -e " ${STYLE_COMMAND}${base} ${STYLE_ARG}${STYLE_RESET}\n" 73 | echo -e " Upload from an URL (the file won't be fetched locally):" 74 | echo -e " ${STYLE_COMMAND}${base} ${STYLE_ARG}${STYLE_RESET}\n" 75 | echo -e " Upload from standard input:" 76 | echo -e " ${STYLE_COMMAND}${base} ${STYLE_ARG}-${STYLE_RESET}\n" 77 | echo -e "The uploaded file's URL is printed to standard output when the upload is completed." 78 | } 79 | 80 | # Process options and arguments 81 | while [[ $# -gt 0 ]]; do 82 | opt="$1" 83 | shift; 84 | case "$opt" in 85 | "-e"|"--expires") 86 | if [[ $# -eq 0 ]] || [[ "$1" =~ ^-{1,2}.* ]]; then 87 | print_error "Missing or invalid argument for expires option" 88 | fi 89 | EXPIRES="$1" 90 | is_number='^[0-9]+$' 91 | if ! [[ $EXPIRES =~ $is_number ]] ; then 92 | print_error "Expires value must be a number" 93 | fi 94 | shift 95 | ;; 96 | "-h"|"--help") 97 | print_help 98 | exit 0 99 | ;; 100 | "-m"|"--mimetype") 101 | if [[ $# -eq 0 ]] || [[ "$1" =~ ^-{1,2}.* ]]; then 102 | print_error "Missing or invalid argument for mimetype option" 103 | fi 104 | MIMETYPE="$1" 105 | ;; 106 | "-n"|"--no-secret") 107 | SECRET=false 108 | ;; 109 | "-v"|"--verbose") 110 | VERBOSE=true 111 | ;; 112 | *) 113 | INPUT_ARG="$opt" 114 | ;; 115 | esac 116 | done 117 | 118 | # Did we get an input argument? 119 | if [[ "$INPUT_ARG" == "" ]]; then 120 | # No input argument 121 | print_help 122 | exit 1 123 | fi 124 | 125 | # Construct an array of opts for the curl command 126 | curl_opts=( "$API_ENDPOINT" ) 127 | 128 | # Add support for verbose logic to curl command 129 | if [[ $VERBOSE == true ]]; then 130 | tmp_file=$(mktemp) 131 | curl_opts=( --no-progress-meter --dump-header "$tmp_file" "${curl_opts[@]}") 132 | fi 133 | 134 | # Add expires to curl opts 135 | if [[ $EXPIRES -gt 0 ]]; then 136 | curl_opts=( -F expires="$EXPIRES" "${curl_opts[@]}" ) 137 | fi 138 | 139 | # Make appropriate curl opts from input 140 | if [[ -f "$INPUT_ARG" || "$INPUT_ARG" = '-' ]]; then 141 | # Upload from file or stdin 142 | if [[ $MIMETYPE != "" ]]; then 143 | INPUT_ARG="$INPUT_ARG;type=$MIMETYPE" 144 | fi 145 | curl_opts=( -F file=@"$INPUT_ARG" "${curl_opts[@]}" ) 146 | 147 | elif [[ "$INPUT_ARG" =~ ^https?://.* ]]; then 148 | # Upload from URL 149 | curl_opts=( -F url="$INPUT_ARG" "${curl_opts[@]}" ) 150 | 151 | elif [[ -d "$INPUT_ARG" ]]; then 152 | print_error "\"$INPUT_ARG\" is a directory." 153 | 154 | else 155 | print_error "\"$INPUT_ARG\": no such file." 156 | fi 157 | 158 | # Add, finally, add use secret if needed 159 | if [[ $SECRET == true ]]; then 160 | curl_opts=( -F secret="" "${curl_opts[@]}" ) 161 | fi 162 | 163 | curl "${curl_opts[@]}" 164 | 165 | if [[ $VERBOSE == true ]]; then 166 | echo -n -e "${STYLE_ARG}" 167 | < "$tmp_file" grep -e x-expires -e x-token | cat 168 | echo -n -e "${STYLE_RESET}" 169 | 170 | rm -f "$tmp_file" 171 | fi 172 | --------------------------------------------------------------------------------