#!/bin/sh

#
#	geo-nearest: Fetch list of nearest geocaches.
#
#	Requires: curl; gpsbabel; bash or ksh;
#		  mysql (if using the gpsdrive.sql output option)
#
#	Donated to the public domain by Rick Richardson <rickr@mn.rr.com>
#	Use at your own risk.  Not suitable for any purpose.  Not legal tender.
#
#	$Id: geo-nearest,v 1.1 2003/01/23 14:05:34 ganter Exp $
#

PROGNAME="$0"

usage() {
	cat <<EOF
Usage:
	`basename $PROGNAME` [options]
	`basename $PROGNAME` [options] latitude longitude
	`basename $PROGNAME` [options] zipcode

	Fetch list of nearest geocaches.

Options:
	-c		Remove cookie file when done
	-n num		Return "num" caches [$NUM]
	-s		Output short names for the caches (gpsbabel option)
	-u username	Username for www.geocaching.com
	-p password	Password for www.geocaching.com
	-o format	Output format, -o? for possibilities [$OUTFMT]
			plus "gpsdrive.sql" for direct insertion into MySQL DB
	-D lvl		Debug level [$DEBUG]

Defaults can be set with variables in file \$HOME/.georc:
	PASSWORD=password;  USERNAME=username;
	LAT=latitude;       LON=logitude;
	NUM=num;            OUTFMT=format;
	SQLUSER=gast;       SQLPASS=gast;        SQLDB=geoinfo;
EOF

	exit 1
}

#
#       Report an error and exit
#
error() {
	echo "`basename $PROGNAME`: $1" >&2
	exit 1
}

#
#       Set default options, can be overriden on command line or in rc file
#
DEBUG=0
COOKIE_FILE=$HOME/.geocookies
ID=20040		# Whats this for?
PASSWORD=dummy
USERNAME=dummy
LAT=44.9472
LON=-93.4914
ZIP=
OUTFMT=gpsdrive
NOCOOKIES=0
BABELFLAGS=
NUM=25
SQLUSER=gast	# For -o gpsdrive.sql
SQLPASS=gast	# For -o gpsdrive.sql
SQLDB=geoinfo	# For -o gpsdrive.sql

#
#	Read RC file, if there is one
#
if [ -f $HOME/.georc ]; then
	. $HOME/.georc
fi

#
#       Process the options
#
SQL=0
unset OPTIND
while getopts "cn:o:p:su:D:h?-" opt
do
	case $opt in
	c)	NOCOOKIES=1;;
	n)	NUM="$OPTARG";;
	s)	BABELFLAGS="$BABELFLAGS -s";;
	u)	USERNAME="$OPTARG";;
	p)	PASSWORD="$OPTARG";;
	o)	OUTFMT="$OPTARG";;
	D)	DEBUG="$OPTARG";;
	h|\?|-)	usage;;
	esac
done
shift `expr $OPTIND - 1`

case "$OUTFMT" in
gpsdrive.sql)
	OUTFMT=gpsdrive
	SQL=1
	# DEBUG=1
	;;
\?)
	gpsbabel -? | sed '1,/Supported/d'
	echo "gpsdrive.sql          GpsDrive direct MySQL database insertion"
	exit
	;;
esac

case "$#" in
2)
	LAT="$1"
	LON="$2"
	SEARCH="?origin_lat=$LAT&origin_long=$LON"
	;;
1)
	ZIP=$1
	SEARCH="?zip=$ZIP"
	;;
0)
	SEARCH="?origin_lat=$LAT&origin_long=$LON"
	;;
*)
	usage
	;;
esac

[ "$USERNAME" != dummy ] || error "You need a www.geocaching.com username"
[ "$PASSWORD" != dummy ] || error "You need a www.geocaching.com password"

#
#	Main Program
#

TMP=/tmp/geo$$
TIMESTAMP=${TMP}.timestamp
GEOWAY=${TMP}.geocaching.loc
OUTWAY=${TMP}.way
CIDS=${TMP}.cids

UA="Mozilla/5.0"
GEO="http://www.geocaching.com"

#
# Go to the cookie store if our cookie's expired.
#
if [ $NOCOOKIES = 1 ]; then
	touch $TIMESTAMP
else
	touch -d "30 minutes ago" $TIMESTAMP
fi
if [ $COOKIE_FILE -ot $TIMESTAMP ]; then
	URL="$GEO/login/default.aspx"
	URL="$URL?ID=$ID&username=$USERNAME&password=$PASSWORD"
	if [ $DEBUG -ge 1 ]; then
		echo "curl $URL" >&2
	fi
	curl -s -D$COOKIE_FILE -A $UA -o /dev/null -L "$URL"
fi
rm -f $TIMESTAMP

#
#	We might combine one or more pages into a single XML, so cobble
#	up a header with the ?xml and loc tags.
#	
cat <<EOF > $GEOWAY
<?xml version="1.0" encoding="ISO-8859-1"?>
<loc version="1.0" src="EasyGPS">
EOF

#
# Loop, getting at least "NUM" locations
#
((start=0))
while ((start < NUM)); do
	#
	# Fetch the page of closest caches and scrape the cache ID's
	#
	URL="$GEO/seek/nearest_cache.asp"
	URL="$URL$SEARCH"
	URL="$URL&start=$start"
	if [ $DEBUG -ge 1 ]; then
		echo "curl $URL" >&2
	fi
	curl -s -b $COOKIE_FILE -A $UA "$URL" \
	| sed -n -e 's/.*name=CID value="\([0-9]*\)".*/-dCID=\1/p' \
	> $CIDS

	#
	# Fetch the waypoints, rip out the ?xml and loc tags, and
	# append to the $GEOWAY file.
	#
	URL="$GEO/waypoints/bulk_waypoints.asp"
	if [ $DEBUG -ge 1 ]; then
		echo "curl $URL" >&2
	fi
	curl -s -b $COOKIE_FILE -A $UA \
		`cat $CIDS` -d "image1.x=71" -d "image1.y=9" "$URL" \
	| sed -e 's/^<?xml [^>]*>//' \
		-e 's/<loc [^>]*>//' \
		-e 's#</loc>##' \
	>> $GEOWAY

	((start=start+25))
done

#
# Convert to desired format
#
echo "</loc>" >> $GEOWAY

if [ $DEBUG -gt 0 ]; then
	cp $GEOWAY /tmp/geocaching.loc
fi

gpsbabel $BABELFLAGS -i geo -f $GEOWAY -o $OUTFMT -F $OUTWAY

gpsdrive_add() {
	delcmd="delete from waypoints"
	addcmd="insert into waypoints (name,lat,lon,type)"
	echo "use $SQLDB;"
	while read name lat lon type extra
	do
		# Primary key is autoincrementing id number, so delete
		# the old record (if any) by name and type
		echo "$delcmd where name='$name' and type='Geocache';"

		# Add the new record
		echo "$addcmd values ('$name','$lat','$lon','Geocache');"
	done
}

if [ -f $OUTWAY ]; then
	if [ $SQL = 1 ]; then
		#
		# add it via mysql
		#
		if [ $DEBUG -gt 0 ]; then
			gpsdrive_add <$OUTWAY
		else
			gpsdrive_add <$OUTWAY | mysql -u$SQLUSER -p$SQLPASS
		fi
	else
		#
		# output to stdout
		#
		cat $OUTWAY
	fi
fi


#
# Remove cruft
#
rm -f $TIMESTAMP $CIDS $GEOWAY $OUTWAY
if [ $NOCOOKIES = 1 ]; then
	rm -f $COOKIE_FILE
fi
