#!/bin/bash # API spec: https://litterbox.catbox.moe/tools.php # curl -F "reqtype=fileupload" -F "time=1h" -F "fileToUpload=@filename" \ # https://litterbox.catbox.moe/resources/internals/api.php # time can be 1h, 12h, 24h, or 72h # The following file types are currently not allowed: # .exe, .scr, .cpl, .doc*, .jar # ...so this script will gzip those automatically. SELF="$( basename $0 )" APIURL="https://litterbox.catbox.moe/resources/internals/api.php" URLS="" EXPIRE="1" DELAY="${DELAY:-2}" UPLOAD_COUNT=0 die() { echo "$SELF: fatal: $@" 1>&2 exit 1 } warn() { echo "$SELF: warning: $@" 1>&2 } info() { [ "$VERBOSE" = "1" ] && echo "$SELF: info: $@" 1>&2 } usage() { cat < $SELF -d [-o output] url License: WTFPL (Do WTF you want with this) EOF } set_expiration() { case "$1" in 1|12|24|72) ;; # OK *) die "invalid expiration time, allowed values are: 1 12 24 72" ;; esac EXPIRE="$1" } add_url() { if [ "$URLS" = "" ]; then URLS="$1" else URLS+=" $1" fi : $(( UPLOAD_COUNT++ )) } copy_urls() { if ! xsel --version &>/dev/null; then warn "xsel not found in PATH, not copying URL(s) to clipboard" return fi if [ "$DISPLAY" = "" ]; then warn "DISPLAY not set in env, not copying URL(s) to clipboard" return fi echo -n "$URLS" | xsel -i } compress_file() { local ext local basefile local is_dir [ -d "$FILE" ] && is_dir=1 if [ "$ZIP" = "1" ]; then ext=.zip else ext=.gz fi basefile="$( basename "$FILE" )" # TODO: create a random tmp dir, don't use /tmp! TMPFILE="${TMP:-/tmp}/$basefile$ext" rm -f "$TMPFILE" if [ "$ZIP" = "1" ]; then zip -qr "$TMPFILE" "$FILE" info "zipped $FILE as $TMPFILE" else if [ "$is_dir" = 1 ]; then tar cfz "$TMPFILE" "$FILE" info "tarred up $FILE as $TMPFILE" else gzip -9 < "$FILE" > "$TMPFILE" info "gzipped $FILE as $TMPFILE" fi fi FILE="$TMPFILE" } # TODO: curl options: # --max-time --retry --retry-max-time upload_file() { local url local use_compression info "checking $FILE" case "$FILE" in *.exe|*.scr|*.cpl|*.doc*|*.jar) warn "forbidden file extension, compression forced" use_compression=1 ;; *) use_compression="$COMPRESS" ;; esac if [ "$use_compression" = 1 ]; then # can't easily zip stdin, write it to a file if [ "$FILE" = "-" ]; then FILE="${TMP:-/tmp}/$SELF.stdin" cat > "$FILE" if [ "$?" != 0 ]; then rm -f "$FILE" return fi fi compress_file # resets FILE, sets TMPFILE fi # at this point, we have an actual file, even if input was stdin, # so we can encrypt it. if [ "$ENC" = "1" ]; then CRYPTFILE="$FILE.aes" openssl enc -pbkdf2 -aes-256-cbc < "$FILE" > "$CRYPTFILE" if [ "$?" != "0" ]; then warn "encryption failed, skipping file" return fi FILE="$CRYPTFILE" fi if [ "$URLS" != "" ]; then info "sleeping $DELAY sec between uploads" sleep "$DELAY" fi info "uploading $FILE" url="$( cat "$FILE" | \ curl --silent \ -F "reqtype=fileupload" \ -F "time=${EXPIRE}h" \ -F "fileToUpload=@-" \ "$APIURL" )" # TODO: check curl's exit status! case "$url" in https://litter.catbox.moe/*) add_url "$url" ;; *) warn "upload failed" ;; esac } download_and_decrypt() { local url="$1" info "downloading and decrypting $url" curl --silent "$url" | openssl enc -d -pbkdf2 -aes-256-cbc [ "$?" != 0 ] && warn "download/decrypt failed" } # main() if [ "$1" = "--help" ]; then usage ; exit 0 fi while getopts ":e:gzcvdo:" OPT; do case "$OPT" in e) set_expiration "$OPTARG"; opt_e=1 ;; o) DLOUT="$OPTARG" ;; g) GZIP=1 ;; z) ZIP=1 ;; c) ENC=1 ;; v) VERBOSE=1 ;; d) DOWNLOAD=1 ;; *) die "invalid option -$OPTARG, try --help" ;; esac done shift $(($OPTIND - 1)) [ "$GZIP" = 1 -a "$ZIP" = 1 ] && die "can't give both -g and -z" [ "$GZIP" = 1 -o "$ZIP" = 1 ] && COMPRESS=1 if [ "$DOWNLOAD" = 1 ]; then [ "$GZIP" = 1 ] && warn "-g option ignored when using -d" [ "$ZIP" = 1 ] && warn "-z option ignored when using -d" [ "$ENC" = 1 ] && warn "-c option ignored when using -d" [ "$opt_e" = 1 ] && warn "-e option ignored when using -d" [ "$DLOUT" != "" ] && exec 1>"$DLOUT" || die "can't redirect stdout" for arg; do download_and_decrypt "$arg" done exit 0 else [ "$DLOUT" != "" ] && warn "-o option ignored when not using -d" fi info "expire time set to $EXPIRE hour(s)" [ "$1" = "" ] && set -- - for arg; do TMPFILE="" CRYPTFILE="" if [ "$arg" = "-" -o -f "$arg" ]; then FILE="$arg" elif [ -d "$arg" ]; then FILE="$arg" compress_file # sets FILE else warn "$arg not a regular file, ignoring" continue fi upload_file if [ "$TMPFILE" != "" ]; then info "removing temp file $TMPFILE" rm -f "$TMPFILE" fi if [ "$TMPFILE" != "" ]; then info "removing temp encrypted file $CRYPTFILE" rm -f "$CRYPTFILE" fi done if [ "$UPLOAD_COUNT" = "0" ]; then die "no files uploaded" fi echo "$URLS" copy_urls info "$UPLOAD_COUNT file(s) uploaded" exit 0