#!/bin/sh #---------------------------------------------------- # Author: Florian "Bluewind" Pritz # Contributor: Moritz Wilhelmy # # Licensed under GPLv3 # (see COPYING for full license text) # #---------------------------------------------------- # Optional dependency: xclip #---------------------------------------------------- VERSION="@VERSION@" DELETE= EXTENSION="" GET= TAR= COMPRESS=0 DISPLAYHISTORY= PASTEBIN="http://paste.xinu.at" WARNSIZE=10485760 CLIPBOARD="" EXITCODE=0 LIBDIR="@LIBDIR@" # the calling conventions for stat(1) are highly system dependent STAT='stat -c %s' # GNU stat(1) is the default since most people have it CLIPBOARD_CMD=xclip case "`uname -s`" in *BSD) STAT='stat -f %z';; Minix) STAT='stat -size';; Darwin) STAT='stat -f %z' CLIPBOARD_CMD=pbcopy ;; esac base64_encode() { if type base64 2>&1 >/dev/null; then printf "%s" "$1" | base64 elif type openssl 2>&1 >/dev/null; then printf "%s" "$1" | openssl enc -base64 else printf "%s\n" "Warning: can't find base64 nor openssl executable" >&2 printf "%s\n" " filename of uploaded file will be set to stdin" >&2 printf "%s\n" "stdin" fi } request_helper() { mode=$1 url=$2 file=$3 # if available use the external helper, else fall back to calling curl if [ -x "$LIBDIR/fb-helper" ]; then $LIBDIR/fb-helper "$mode" "$url" "$file" else USERAGENT="fb-client/shell-$VERSION" CURLOPTS="-# -n -L -A $USERAGENT" if [ "$mode" = "d" ]; then CURLOPTS="$CURLOPTS -s" fi if [ "$mode" = "u" ]; then basefilename=`basename -- "$file"` if [ "`$STAT -- "$file"`" -eq "0" ] || printf "%s" "$basefilename" | grep -F -q ","; then if [ "`wc -c -- "$file" | cut -d\ -f1`" -eq "0" ]; then printf "%s\n" "Error: skipping 0-byte file: \"$file\"" >&2 return 1 fi base64fn="`base64_encode "$basefilename"`" curl $CURLOPTS -F "file=@-" -F "filename=$base64fn" "$url" < "$file" -o /dev/stdout else curl $CURLOPTS -F "file=@$file" "$url" -o /dev/stdout fi else curl $CURLOPTS "$url" fi fi } require_executable() { if ! type $1 >/dev/null; then printf "%s\n" "Error: $1 not found. Please install." >&2 exit 1 fi } is_url() { if printf "%s" "$i" | grep -qE "^(f|ht)tp(s)?://.+"; then return 0 fi return 1 } do_tar_upload() { if [ "$COMPRESS" = "1" ]; then file="$TMPDIR/upload.tar.gz" tar -cf - -- "$@" | gzip -c > "$file" || return 1 elif [ "$COMPRESS" = "2" ]; then file="$TMPDIR/upload.tar.xz" tar -cf - -- "$@" | xz -c > "$file" || return 1 else file="$TMPDIR/upload.tar" tar -cf "$file" -- "$@" || return 1 fi COMPRESS=0 do_upload "$file" || return 1 } do_upload() { local EXTRA="" file="$1" basefilename="`basename -- "$file"`" basedirname="`dirname -- "$file"`" if [ ! -r "$file" ]; then # sh doesn't have perror so this message can't be more precise printf "%s\n" "Error: File \"$file\" is not readable/not found." >&2 return 1 fi if [ -d "$file" ]; then cd "$basedirname" if [ "$COMPRESS" = "1" ]; then file="$TMPDIR/$basefilename.tar.gz" tar -cf - -- "$basefilename" | gzip -c > "$file" || return 1 elif [ "$COMPRESS" = "2" ]; then file="$TMPDIR/$basefilename.tar.xz" tar -cf - -- "$basefilename" | xz -c > "$file" || return 1 else file="$TMPDIR/$basefilename.tar" tar -cf "$file" -- "$basefilename" || return 1 fi else if [ "$COMPRESS" = "1" ]; then gzip -c -- "$file" > "$TMPDIR/$basefilename.gz" || return 1 file="$TMPDIR/$basefilename.gz" elif [ "$COMPRESS" = "2" ]; then xz -c -- "$file" > "$TMPDIR/$basefilename.xz" || return 1 file="$TMPDIR/$basefilename.xz" fi fi TMPFILE=`mktemp "$TMPDIR/data.XXXXXX"` if [ "`$STAT -- "$file"`" -gt "$WARNSIZE" ]; then WARNSIZE=`request_helper d "$PASTEBIN/file/get_max_size"` if [ "`$STAT -- "$file"`" -gt "$WARNSIZE" ]; then printf "%s\n" "Warning: Your upload is too big and would be rejected. Maximum size is: $WARNSIZE bytes. Skipping..." >&2 return 1 fi fi request_helper u "$PASTEBIN/file/do_upload" "$file" > $TMPFILE || return 1 sed '$d' $TMPFILE >&2 URL=`tail -1 $TMPFILE`"$EXTENSION" printf "%s\n" "$URL" if printf "%s" "$URL" | grep -qE "^https?://"; then if [ -z "$CLIPBOARD" ]; then CLIPBOARD="$URL" else CLIPBOARD="$CLIPBOARD $URL" fi fi } read_stdin() { if tty -s; then printf "%s\n" "^C to exit, ^D to send" fi cat > "$1" } id_from_arg() { if printf "%s" "$1" | grep -qE "^https?://"; then printf "%s" "$1" | sed -r 's/https?:\/\/[^\/]+\/([^\/]+).*/\1/' else printf "%s" "$1" fi } help() { cat <] Upload/nopaste file(s)/stdin to paste.xinu.at and copy URL(s) to clipboard. ~/.netrc: machine paste.xinu.at password PASSWORD Switches: -d delete the IDs -g download the IDs and output on stdout (use with care!) -h this help -v show the client version -H display an upload history Options: -e extension for default highlighting (e.g. "diff") -t upload a tar file containing all files (and directories) -c compress the file being uploaded with gz or xz if used 2 times When used in conjunction with -g this decompresses the download ! } if ! type getopts >/dev/null 2>&1; then printf "%s\n" "Error: getopts is not supported by your shell" >&2 exit 1 fi while getopts "e:gdhHtcv" OPTION; do case $OPTION in e) EXTENSION="$OPTARG";; g) GET=1;; c) COMPRESS=`expr $COMPRESS + 1`;; t) TAR=1;; d) DELETE=1;; H) DISPLAYHISTORY=1;; v) printf "%s\n" "$VERSION"; exit 0;; h|\?) help; exit 0;; esac done shift `expr $OPTIND - 1` if [ "$COMPRESS" = "1" ]; then require_executable gzip elif [ "$COMPRESS" = "2" ]; then require_executable xz fi TMPDIR="`mktemp -dt "fb.XXXXXX"`" trap "rm -rf '${TMPDIR}'" EXIT TERM if [ "$DELETE" ] || [ "$GET" ]; then if [ $# -eq 0 ]; then printf "%s\n" "Error: no ID specified" >&2 exit 1 fi for i in "$@"; do i=$(id_from_arg "$i") if [ "$DELETE" ]; then request_helper d "$PASTEBIN/file/delete/$i" || EXITCODE=1 elif [ "$GET" ]; then if [ "$COMPRESS" = "1" ]; then request_helper d "$PASTEBIN/$i" | gzip -cd || EXITCODE=1 elif [ "$COMPRESS" = "2" ]; then request_helper d "$PASTEBIN/$i" | xz -cd || EXITCODE=1 else request_helper d "$PASTEBIN/$i" || EXITCODE=1 fi fi done elif [ "$DISPLAYHISTORY" ]; then request_helper d "$PASTEBIN/file/upload_history" || EXITCODE=1 elif [ $# -eq 0 ]; then if [ "$TAR" ]; then printf "%s\n" "Error: -t is not supported when operating on stdin" >&2 exit 1 fi read_stdin "$TMPDIR/stdin" do_upload "$TMPDIR/stdin" || EXITCODE=1 else if [ "$TAR" ]; then HAVE_URL= for i in "$@"; do if is_url "$i"; then HAVE_URL=1 fi done if [ "$HAVE_URL" ]; then # TODO: support -t when passing URLs as arguments printf "%s\n" "Error: -t is not yet supported when operating on a URL" >&2 exit 1 else do_tar_upload "$@" || EXITCODE=1 fi else for i in "$@"; do if is_url "$i"; then cd $TMPDIR if ! request_helper d "$i" > "`basename "$i"`"; then EXITCODE=1 continue fi for f in *; do if ! do_upload "$f"; then EXITCODE=1 fi rm -f -- "$f" done else do_upload "$i" || EXITCODE=1 fi done fi fi if [ "$CLIPBOARD" != "" ]; then type $CLIPBOARD_CMD >/dev/null 2>&1 && printf "%s" "$CLIPBOARD" | nohup $CLIPBOARD_CMD >/dev/null 2>&1 fi exit $EXITCODE #vim: set noet: