#/bin/bash
#
# Send and XML-RPC "pingback" request to a server
#
# Usage: pingback myurl yoururl
#
# The program sends a request to the server of yoururl, asking it to
# include a link to myurl on the yoururl page. If yoururl is a typical
# blog server, it might actually do that.
#
# The pingback spec: http://www.hixie.ch/specs/pingback/pingback
# The XML-RPC spec: http://www.xmlrpc.com/spec
#
# Created: 26 May 2007
# Author: Bert Bos
# Copyright: 2007 © W3C
# see  http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231

VERSION=1.0


# die -- print message and exit with error code
function die
{
  echo "$1" >&2
  exit 1
}


# Main body
#
trap 'rm -f $page $headers $body' 0
page=`tempfile` || die "Cannot create temporary file."
headers=`tempfile` || die "Cannot create temporary file."
body=`tempfile` || die "Cannot create temporary file."

# Find out which option enables extended regexps in sed: -E or -r
# (This is different between Mac OS X (BSD) and Linux :-( )
#
sed -E p /dev/null 2>/dev/null && ext="-E" || ext="-r"

# Get the remote page, look for a pingback URL in the HTTP headers or,
# failing that, in the page itself.
#
curl --silent --location --dump-header $headers "$2" >$page || \
 die "Failed to get remote page. Aborted."

pingbackurl=`grep -i '^x-pingback *:' $headers | head -1 | tr -d ' \r\n\t'`
pingbackurl="${pingbackurl#*:}"

if [ -z "$pingbackurl" ]; then
  pingbackurl=`sed $ext -n\
   -e '/<link rel="pingback" href="[^"][^"]*" ?\/?>/!d' \
   -e 's|.*<link rel="pingback" href="([^"][^"]*)" ?/?>.*|\1|' \
   -e 's|&amp;|&|g' \
   -e 's|&lt;|<|g' \
   -e 's|&gt;|>|g' \
   -e 's|&quot;|"|g' \
   -e 'p' \
   -e 'q' \
   $page`
fi

[[ -z "$pingbackurl" ]] && die "No pingback URL found in remote resource."

# Split pingbackurl into server, port and path.
#
port="${pingbackurl#http://}"
port="${port%%/*}"
path="${pingbackurl#http://$port}"
server="${port%:*}"
port="${port#$server}"
port="${port:-80}"

# Escape XML delimiters in myurl and yoururl
#
source="${1//&/&amp;}"
source="${source//</&lt;}"
source="${source//>/&gt;}"
target="${2//&/&amp;}"
target="${target//</&lt;}"
target="${target//>/&gt;}"

# To do: if the URL contains non-ASCII characters, UTF-8 encode them
# and then escape the UTF-8 codes as %hex codes...

# Create the XML RPC document and compute its size
#
cat >$body <<-EOF
	<methodCall>
	<methodName>pingback.ping</methodName>
	<params>
	<param><value>$source</value></param>
	<param><value>$target</value></param>
	</params>
	</methodCall>
	EOF
typeset -i length=`cat $body | wc -c`

# Send a pingback.ping XML RPC request to the pingbackurl.
#
(
  echo "POST $path HTTP/1.0"
  echo "User-Agent: pingback.sh/$VERSION"
  echo "Host: $server"
  echo "Content-Type: text/xml"
  echo "Content-Length: $length"
  echo
  cat $body
) | nc $server $port

echo
