--- /dev/null
+#!/bin/bash
+
+# Copyright (c) 2009 Florian Reitmeir
+# Copyright (c) 2009 Peter Palfrader
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+# Author: Florian Reitmeir
+# E-mail: florian@reitmeir.org
+
+# Publishes files on a webserver.
+#
+# This script copies files or directories as given on the command line,
+# or stdin or the xclipboard, to a remote location using rsync. That
+# remote directory should be exposed online and ideally be o-r or have
+# indexing disabled.
+#
+# The directory names chosen by this script are random(ish) but still
+# contain a date string so one know how old things are when looking at them
+# (Or one can just have cron clean out stuff older than a week or a month
+# automagically).
+#
+# The random location chosen is printed to stdout when the script finishes,
+# and is copied to the xclipboard if the xclip(1) utility is installed·
+#
+# base_http and base_rsync can be overriden in a ~/.publish.cfg shell snippet.
+
+base_http=http://www.example.com/pub
+base_rsync=marvin.example.com:/var/www/www.example.com/htdocs/pub
+
+history_file=~/.publish.history
+history_lines=1000
+
+date_format='%Y-%m-%d-'
+
+rsync_pre_invoke() { true ;}
+rsync_post_invoke() { true ;}
+publish_pre_invoke() { true ;}
+publish_post_invoke() { true ;}
+
+[ -e ~/.publish.cfg ] && . ~/.publish.cfg
+
+usage()
+{
+cat << EOF
+usage: $0 [<src> [<src> ...]]
+
+copy the file <src> to a server an report the URL.
+
+OPTIONS:
+ -n no-do. Just print what would have been done
+ -s Show the history
+ -x Publish the contents of the xclipboard
+ -h Show this message
+EOF
+}
+
+uri_encode() {
+ perl -MURI::Escape -ne 'print uri_escape($_)'
+}
+
+get_random() {
+ head -c 8 /dev/urandom | base64 | tr '/+' 'xx' | tr -d '='
+}
+
+history_append() {
+ time=$(date --utc --rfc-3339='seconds')
+ echo $time $1 >>"$history_file"
+
+ history_tmp=$( tempfile )
+ cat "$history_file" | tail --lines="$history_lines" >"$history_tmp"
+ mv "$history_tmp" "$history_file"
+}
+
+history_show() {
+ cat "$history_file"
+}
+
+NODO=""
+inputxclip=0
+
+while getopts "hnsx" OPTION
+do
+ case $OPTION in
+ h)
+ usage
+ exit
+ ;;
+ n)
+ NODO="echo"
+ ;;
+ x)
+ inputxclip=1
+ ;;
+ s)
+ if [ -r "$history_file" ]; then
+ history_show
+ exit 0
+ else
+ echo "history file: '$history_file' not found"
+ exit 3
+ fi
+ ;;
+ *)
+ usage >&2
+ exit 1
+ ;;
+ esac
+done
+shift $(($OPTIND - 1))
+
+if [[ "$#" = 0 ]]; then
+ stdin=`tempfile`
+ trap "rm -f '$stdin'" EXIT
+ chmod a+r "$stdin"
+
+ if [ "$inputxclip" != 1 ] ; then
+ echo "No files given on the command line, using stdin" >&2
+ cat > "$stdin"
+ else
+ if which xclip >/dev/null 2>&1; then
+ echo "Publishing x clipboard:" >&2
+ xclip -o > "$stdin"
+ cat "$stdin" | sed -e 's#^#| #'
+ echo
+ echo "EOF"
+ else
+ echo "xclip not installed?" >&2
+ exit 1
+ fi
+ fi
+ set dummy "$stdin"
+ shift
+elif [ "$inputxclip" = 1 ] ; then
+ echo "Ignoring -x because there are files on the command line" >&2
+fi
+
+d_date=$(date +"$date_format")
+d_random=$(get_random)
+d_server="$d_date$d_random"
+rsync_args="--partial --recursive --compress --times"
+
+d_server_http_base=$( echo -n "$d_server" | uri_encode )
+
+if [ "$#" = 1 ]; then
+ only_one=1
+else
+ only_one=0
+ echo "$base_http/$d_server_http_base/"
+ if which xclip >/dev/null 2>&1; then
+ echo -n "$base_http/$d_server_http_base/" | xclip
+ fi
+fi
+
+
+publish_pre_invoke
+
+while [ "$#" -gt 0 ]; do
+ file="$1"
+ shift
+
+ uri="$base_http/$d_server_http_base/$( echo -n "`basename "$file"`" | uri_encode )"
+
+ trail=""
+ if [ "$only_one" = 1 ]; then
+ if [ -d "$file" ]; then
+ trail="/"
+ uri="$base_http/$d_server_http_base/"
+ fi
+ if which xclip >/dev/null 2>&1; then
+ echo -n "$uri" | xclip
+ fi
+ fi
+
+ echo "$uri"
+ history_append "$uri"
+
+ rsync_pre_invoke
+ $NODO rsync $rsync_args "$file$trail" $base_rsync"/$d_server/"
+ rsync_post_invoke
+done
+
+publish_post_invoke