#!/usr/bin/bash # Copyright (c) 2012 fbt # License: ISC # # About: # A simple upload script for UFW (http://zerofiles.org) _cat() { while read; do printf '%s\n' "$REPLY" done } is_url() { [[ "$1" =~ $cfg_url_regex ]] } msg() { if ! (( flag_quiet )); then printf '%s\n' "$1" fi } err() { printf '(error) %s\n' "$*" >&2; } usage() { _cat <<- EOF Usage: ufw [-RsF] [-D num] [file/url]" Flags: -R|--remove-file # Remove the file after uploading. -s|--screenshot # Make a screenshot and upload it instead of a file. -F|--fullscreen # Make a fullscreen shot instead of prompting for a window/area. Implies -s. -d|--description # Supply a description. -D|--screenshot-delay # Delay the shot by seconds. -p|--public # Make the file public. -u|--shorten # Generate a shortlink from URL. -S|--short-url # Get a shortlink when uploading a file. -P|--page-url # Get a link to the file page instead of a direct one. -m|--max-filesize [suf] # Maximum filesize (takes K, M and G suffixes). -a|--album-id # Add the file to an album. -A|--album-name # Add the file to an album by name. The album will be created, if necessary. Config options (~/.config/ufw): secret # Your personal token. Get it at https://zfh.so/settings_form cfg_screenshot_ext # Screenshot file type, used by maim. cfg_max_filesize # Maximum filesize (takes K, M and G suffixes). # Others are self-explanatory: cfg_url_regex cfg_tmp_dir cfg_service_url cfg_api_path EOF } get_file_hash() { read file_hash _ < <( sha1sum "$1" ) } get_max_filesize() { if [[ $cfg_max_filesize =~ ^[0-9]+[BKMG]?$ ]]; then max_filesize_base="${cfg_max_filesize//[BKMG]/}" case "$cfg_max_filesize" in *K) max_filesize_bytes=$(( max_filesize_base * 1024 ));; *M) max_filesize_bytes=$(( max_filesize_base * 1024 * 1024 ));; *G) max_filesize_bytes=$(( max_filesize_base * 1024 * 1024 * 1024 ));; *) max_filesize_bytes=$max_filesize_base;; esac else err "Wrong cfg_max_filesize: $cfg_max_filesize" return 1 fi } get_album_id() { declare api_response api_status api_status_message api_response=$( curl -fsL "$cfg_service_url/$cfg_api_path/album?a=new&name=$1&format=json&secret=$secret" ) get_api_status <<< "$api_response" if (( api_status == 200 )); then album_id=$( jshon -e data -e album -e id -u <<< "$api_response" ) misc_curl_args+=( -F album_id="$album_id" ) else printf 'Error [album]: %s %s\n' "$api_status" "$api_status_message" return 1 fi } upload() { declare api_response api_status api_status_message if (( flag_scn )); then flag_rm=1 file=$(take_screenshot) || { return 1; } else (( $# )) || { usage return 1 } target="$1" if is_url "$target"; then flag_rm=1 file=$(_mktemp "$cfg_tmp_dir") get_max_filesize || { return 1; } curl --max-filesize "$max_filesize_bytes" -skL "$target" > "$file" curl_result=$? if (( curl_result )); then case "$curl_result" in 63) err "File exceeds cfg_max_filesize";; *) err "Could not download file.";; esac return 1 fi else file="$target" [[ -f "$file" ]] || { err "No such file: ${file}" return 1 } fi fi get_file_hash "$file" if [[ "$album_name" ]]; then get_album_id "$album_name" fi api_response=$( curl -sL \ -F file="@$file" \ -F api_format='json' \ -F flag_private="$flag_private" \ -F secret="$secret" \ -F submit="" \ "${misc_curl_args[@]}" \ -A 'zerofiles.org upload script' \ "$cfg_service_url/$cfg_api_path/upload" ) if (( flag_shortlink )); then if (( flag_directlink )); then file_url_request='short_url_direct' else file_url_request='short_url' fi else if (( flag_directlink )); then file_url_request='direct_url' else file_url_request='page_url' fi fi get_api_status <<< "$api_response" if (( api_status == 200 )); then file_link=$( jshon -e data -e file -e "$file_url_request" -u <<< "$api_response" ) printf '%s\n' "$file_link" if (( flag_rm )); then msg "Removing file: $file" rm "$file" fi else printf 'Error: %s %s\n' "$api_status" "$api_status_message" return 1 fi } get_shortlink() { declare url=$1 api_response api_status api_status_message api_response=$( curl -sL "$cfg_service_url/$cfg_api_path/url?a=add&url=${url}&format=json&secret=$secret" ) get_api_status <<< "$api_response" if (( api_status == 200 )); then read -r short_url real_url < <( jshon -e data -e URL -e shorturl -u <<< "$api_response" ) printf '%s\n' "$short_url" else printf 'Error: %s %s\n' "$api_status" "$api_status_message" fi } take_screenshot() { declare tmp_file [[ "$scn_exec" ]] || { scn_exec=$(type -P maim); } [[ "$scn_exec" ]] || { err "Please install maim to use this function" return 1 } (( "$flag_scn_fullscreen" )) || { scn_args+=( '-s' ); } [[ "$cfg_scn_delay" ]] && { scn_args+=( "-d $cfg_scn_delay" ); } tmp_file="$(_mktemp "${cfg_tmp_dir}" ".${cfg_screenshot_ext}")" maim "${scn_args[@]}" "$tmp_file" || { err "Failed to take a screenshot." return 1 } printf '%s\n' "$tmp_file" } get_api_status() { read -d '' -r api_status api_status_message < <( jshon -e status -e code -u -p -e message -u ) if ! (( api_status == 200 )); then return 1 fi } _mktemp() { declare tmp_file_name tmp_file_name_extra="$2" tmp_dir="$1" [[ -d "$tmp_dir" ]] || { err "${tmp_dir} does not exist or is not a directory." return 1 } until [[ ! -e "${tmp_dir}/${tmp_file_name}" ]]; do tmp_file_name="${RANDOM}${RANDOM}${tmp_file_name_extra}" done printf '%s\n' "${tmp_dir}/${tmp_file_name}" } get_my_ip() { declare api_response api_status api_status_message my_ip api_response=$( curl -sl "$cfg_service_url/$cfg_api_path/ip?format=json" ) get_api_status <<< "$api_response" if (( api_status == 200 )); then my_ip=$( jshon -e data -e ip -u <<< "$api_response" ) printf '%s\n' "$my_ip" else printf 'Error: %s %s\n' "$api_status" "$api_status_message" fi } login() { declare api_response api_response=$( curl -sl "$cfg_service_url/$cfg_api_path/get_login_token?login=$login&format=json" ) if get_api_status <<< "$api_response"; then printf 'Check your email.\n' else printf 'Error: %s %s\n' "$api_status" "$api_status_message" fi } set_argv() { declare arg opt c declare -g argv while (( $# )); do unset -v arg opt c case "$1" in (--) argv+=( "$1" ); break;; (--*) IFS='=' read arg opt <<< "$1" argv+=( "$arg" ) [[ "$opt" ]] && { argv+=( "$opt" ) } ;; (-*) while read -n1 c do case "$c" in -|'') :;; *) argv+=( "-$c" );; esac done <<< "$1" ;; (*) argv+=( "$1" );; esac shift done } main() { declare args file target flag_private flag_rm flag_scn flag_scn_fullscreen cfg_scn_delay declare flag_shortlink=0 # Defaults for XDG if ! [[ "$XDG_RUNTIME_DIR" ]]; then XDG_RUNTIME_DIR="/run/user/$UID" fi if ! [[ "$XDG_CONFIG_DIR" ]]; then XDG_CONFIG_DIR="$HOME/.config" fi cfg_url_regex='^[A-Za-z]([A-Za-z0-9+.-]+)?://.+' cfg_tmp_dir="$XDG_RUNTIME_DIR/ufw"; TEMPDIR="$cfg_tmp_dir" cfg_service_url='https://8fw.me' cfg_screenshot_ext='png' cfg_max_filesize='200M' cfg_api_path='/api/2' flag_shortlink=0 flag_directlink=1 if [[ -f "$HOME/.suprc" ]]; then printf 'Found legacy configfile, moving...\n' >&2 mv "$HOME/.suprc" "$XDG_CONFIG_DIR/ufw" fi if [[ -f "$XDG_CONFIG_DIR/ufw" ]]; then if ! source "$XDG_CONFIG_DIR/ufw"; then printf 'Failed to source configuration file: %s\n' "$XDG_CONFIG_DIR/ufw" return $? fi fi while [[ "$1" ]]; do case "$1" in -h|--help|--usage) usage; return;; -D|--screenshot-delay) cfg_scn_delay="$2"; shift;; -m|--max-filesize) cfg_max_filesize=$2; shift;; -A|--album-name) album_name=$2; shift;; -i|--my-ip) action='getmyip';; -u|--shorten) action='url';; -p|--public) flag_private='false';; -R|--remove-file) flag_rm='1';; -s|--screenshot) flag_scn='1';; -S|--short-url) flag_shortlink=1;; -P|--page-url) flag_directlink=0;; -q|--quiet) flag_quiet=1;; -F|--fullscreen) flag_scn='1' flag_scn_fullscreen='1' ;; -a|--album-id) misc_curl_args+=( -F "album_id=$2" ) shift ;; -d|--description) misc_curl_args+=( -F "description=$2" ) shift ;; --) shift; break;; -*) err "Unknown flag: $1" usage return 1 ;; *) break;; esac shift done for i in "$cfg_tmp_dir"; do [[ -d "$i" ]] || { mkdir -p "$i"; } done case "${action:-upload}" in upload) for t in "$@"; do upload "$t" done ;; url) for t in "$@"; do get_shortlink "$1" done ;; getmyip) get_my_ip;; login) login;; esac } set_argv "$@" main "${argv[@]}"