#!/bin/bash # # # DO NOT EDIT! This file is generated from geo-soon.sh # # # HACK ALERT! This was quickly hacked from an existing script, # and needs to be merged back into the main codebase. # # # Donated to the public domain by Rick Richardson # # Use at your own risk. Not suitable for any purpose. Not legal tender. # # $Id: geo-soon.sh,v 1.37 2011/04/04 04:56:06 rick Exp $ # PROGNAME="$0" usage() { cat <&2 exit 1 } debug() { if [ $DEBUG -ge $1 ]; then echo "`basename $PROGNAME`: $2" >&2 fi } verbose() { if [ $VERBOSE -ge $1 ]; then echo "$2" >&2 fi } dbgcmd() { if [ $DEBUG -ge $DBGCMD_LVL ]; then echo "$@" >&2 fi "$@" } DBGCMD_LVL=2 # # procedure to remove cruft files # remove_cruft() { if [ $DEBUG = 0 -a "$CRUFT" != "" ]; then for i in $CRUFT do [ -f $i ] && rm -f $i done fi } trap remove_cruft EXIT # # Convert DegDec, MinDec, or DMS lat/lon to DegDec # latlon() { # Handle NSEW prefixes arg1=`echo "$1" | sed -e 's/^[nNeE]//' -e 's/^[wW]/-/' -e 's/^[sS]/-/'` # If negative, print the sign then take the absolute value case "$arg1" in -*) echo -n "-"; arg1=`echo "$arg1" | sed 's/^-//'`;; esac # Now handle the 3 different formats case $# in 1) case "$arg1" in *.*.*) echo "$arg1" \ | sed -e 's/,//' -e 's#\([^.]*\)\.#\1 #' -e 's#$# 6k 60/+p#' \ | dc ;; lat=*) echo "$arg1" | sed 's/^lat=//' ;; lon=*) echo "$arg1" | sed 's/^lon=//' ;; *) echo $arg1 ;; esac ;; 2) echo "6k $arg1 $2 60/+p" | dc;; 3) echo "6k $arg1 $2 60/ $3 3600/++p" | dc;; esac } # # Convert DegDec to MinDec # degdec2mindec() { awk -v v=$1 \ 'BEGIN{ i=int(v); f=(v-i)*60; if(f<0)f=-f; printf "%d.%06.3f\n", i, f}' } # # Read RC file, if there is one # read_rc_file() { if [ -f $HOME/.georc ]; then . $HOME/.georc # Allow LAT/LON in rc file to be in any of the formats that we grok if [ "" != "$LAT" ]; then if ! is_latlon $LAT 0; then error "Latitude '$LAT' is not parsed in .georc!" fi LAT=`latlon $LAT` fi if [ "" != "$LON" ]; then if ! is_latlon 0 $LON; then error "Longitude '$LON' is not parsed in .georc!" fi LON=`latlon $LON` fi else cat <<-EOF > $HOME/.georc # # These are the default values for the geo-* series of programs # Please edit this file as needed. Setting values for # USERNAME, PASSWORD, LAT/LON, and STATE are required. # ################################# # Login and paid membership status for www.geocaching.com... #USERNAME=name #PASSWORD=pasword #SOC=0 ################################# # Your HOME lat/lon and state... #LAT=N44.55.666 #LON=W93.11.222 #STATE=MN ################################# # Default map scale, font, and source... #MAPSCALE=10K #MAPFONT=helvetica #MAPSRC=2 ################################# # Login for terraserver.com... #TSCOM_EMAIL=xxx@yyy.com #TSCOM_PW=password ################################# # Miscellaneous... #OUTFMT=gpsdrive #GPSDRIVE_VER=2.09 #CURL_OPTS="-4" EOF error "First time user: please review and edit $HOME/.georc" fi } if [ `uname` = 'Darwin' ]; then sed=gsed date=gdate touch=gtouch PATH=$PATH:/usr/local/bin:/opt/local/bin export PATH else sed=sed date=date touch=touch fi # # Get the value from a name= value= pair in a file # get_value() { # = 97 && val <= 122) #0x61-0x7A encoded = encoded c else if (val >= 65 && val <= 90) #0x41-0x5A encoded = encoded c else if (val >= 48 && val <= 57) #0x30-0x39 encoded = encoded c else if (val >= 45 && val <= 46) #0x2D-0x2E encoded = encoded c else if (c == " ") encoded = encoded "+" else if (val < 128) { lo = val % 16 hi = int(val / 16); encoded = encoded "%" hextab[hi] hextab[lo] } else { byte = 192 + val/64 lo = byte % 16 hi = int(byte / 16); encoded = encoded "%" hextab[hi] hextab[lo] byte = 128 + val%64 lo = byte % 16 hi = int(byte / 16); encoded = encoded "%" hextab[hi] hextab[lo] } } print encoded } ' } # # return true if current arguments appear to be a lat/lon # is_latlon() { if [ "$#" -lt 2 ]; then return 1 fi case "$1" in lat=*) ;; # cut/paste from GPX file [NS]) return 0;; # cut/paste from gc.com [NSns][0-9]*) ;; [-][0-9]*) ;; [0-9]*) ;; *) return 1;; esac case "$2" in lon=*) return 0;; [EWew][0-9]*) return 0;; [-][0-9]*) return 0;; [0-9]*) return 0;; *) return 1;; esac } # # split lines between two strings # # $1 - string 1 # $2 - string 2 # $3 - null or 'g' # split_lines_between() { sed "s@$1$2@$1\\ $2@$3" } ############################################################################## # end #include "geo-common" ############################################################################## ############################################################################## # begin #include "geo-common-gc" # # $Id: geo-common-gc,v 1.284 2012/01/23 16:59:13 rick Exp $ ############################################################################## # # Common global constants # UA="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)" UA="Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/XX (KHTML, like Gecko) Version/ZZ Safari/YY" GEO="http://www.geocaching.com" GEOS="https://www.geocaching.com" # # Global variables that can be overridden on command line or rc file # PASSWORD=dummy USERNAME=dummy LAT=44.9472 LON=-93.4914 SOC=${SOC:0} GEOMYSTERY=/dev/null GEODIR=$HOME/.geo case `uname` in CYGWIN*) CURL_OPTS=-k;; *) CURL_OPTS= esac # # Global variables # COOKIE_FILE=$HOME/.geocookies NOCOOKIES=0 FOUND=1 USERFOUND=1 BABELFLAGS= RADIUS= OUTFILE= OUTFMT=gpsdrive NUM=20 INCLUDE=* EXCLUDE='-unavail' VARTIME=found GEOSLEEP=${GEOSLEEP:-8} # # Common options handling # gc_usage() { cat < $LOGINPAGE if [ ! -s $LOGINPAGE ]; then error "curl: returned /dev/null for '$LOGINPAGE'" fi if grep -q "ErrorText" $LOGINPAGE; then error "Login username/password does not match." fi if grep -q "If you are human" $LOGINPAGE; then error "Have to login this time with a web browser because of Recaptcha" fi if ! grep -q "You are logged in as <[^>]*>$_username<" $LOGINPAGE; then error "BUG: gc.com changed the login page." fi } # # procedure to nag about agreeing to EasyGps download license # easy_warning() { cat <<-EOF You have not agreed to the waypoint download license at $GEO Click one of the waypoint license agreement links at $GEO, read and agree to the license terms, then try this program again. EOF } # # getcids infile cidfile xtrafile archfile number # # Wade thru the HTML and produce lists of found, notfound and new CIDs # getcids() { awk \ -v "CIDFILE=$2" \ -v "XTRAFILE=$3" \ -v "ARCHFILE=$4" \ -v "NUM=$5" \ -v "USERFOUND=$USERFOUND" \ -v "VARTIME=$VARTIME" \ -v "SOC=$SOC" \ -v "DATE=$date" \ -v "DATEFMT=$DATEFMT" \ -v "DEBUG=$DEBUG" \ < $1 \ ' function debug(lvl, text) { if (lvl <= DEBUG) print text > "/dev/stderr" } function hex2dec(x, val) { for (val = 0; length(x); x = substr(x, 2)) val = 16*val + index("0123456789ABCDEF", substr(x, 1, 1)) - 1 return val } # Convert GC0000 to 58913 function wp2id(wp, val) { sub("^GC", "", wp) if (DEBUG > 5) print "wp2id: " wp " ..." > "/dev/stderr" if (length(wp) <= 4 && wp < "G000") { val = hex2dec(wp) if (DEBUG > 5) print "wp2id hex: " val " ..." > "/dev/stderr" return val } set = "0123456789ABCDEFGHJKMNPQRTVWXYZ" val = 0 for (pos = 1; pos <= length(wp); ++pos) { val *= 31; val += index(set, substr(wp, pos, 1)) - 1; } val = val - 411120 if (DEBUG > 5) print "wp2id id: " val " ..." > "/dev/stderr" return val } function id2wp(id, val) { gid = ""; if (id < 0) ; else if (id < 65536) gid = sprintf("GC%04X", id) else { GcOffset = 16 * 31 * 31 * 31 - 65536 GcSet = "0123456789ABCDEFGHJKMNPQRTVWXYZ" id += GcOffset; for (i = 1; i <= 4; ++i) { gid = substr(GcSet, id%31 + 1, 1) gid id = int(id / 31) } tmp = substr(GcSet, id%31 + 1, 1) if (tmp != 0) { gid = tmp gid id = int(id / 31) } if (id) gid = "" else gid = "GC" gid } if (DEBUG >= 5) print "id = ", id, "wp = ", gid > "/dev/stderr" return gid } function hash2sdt(text, value, mod, sizePre, diff, terrainPre, difficultyPre) { if (ratingKey == "") ratingKey = "hbM9fjmrxy7z42LFD58BkKgPGdHscvCqNnw3ptO6lJ" # cut leading zero if (length(text) > 6) text = substr(text, length(text) - 6 + 1) # add missing leading zero while (length(text) < 6) text = "h" text for (i = 0; i < 6; i ++) { value += (index(ratingKey, substr(text, i+1, 1)) - 1) \ * (42 ^ (5 - i) ); } # debug(5, "sdk value: " value) mod = (value - 131586) % 16777216 sizePre = int(mod / (42 ^ 3)); if (sizePre == 0) diff = 0 else if (sizePre == 1) diff = 131072 else if (sizePre == 3) diff = 262144 else if (sizePre == 5) diff = 393217 else if (sizePre == 7) diff = 524288 else if (sizePre == 8) diff = 655360 else if (sizePre == 12) diff = 917504 else diff = -1 terrainPre = int((mod - diff) / 252) difficultyPre = int(((mod - diff) % 42) - (terrainPre * 4)) # cache size if (sizePre == 0) size = "not chosen" else if (sizePre == 1) size = "Micro" else if (sizePre == 3) size = "Regular" else if (sizePre == 5) size = "Large" else if (sizePre == 7) size = "Virtual" else if (sizePre == 8) size = "Unknown" else if (sizePre == 12) size = "Small" else size = "BUG" # terrain rating if (terrainPre == 0) terrain = 1.0 else if (terrainPre == 1) terrain = 1.5 else if (terrainPre == 2) terrain = 2.0 else if (terrainPre == 3) terrain = 2.5 else if (terrainPre == 4) terrain = 3.0 else if (terrainPre == 5) terrain = 3.5 else if (terrainPre == 6) terrain = 4.0 else if (terrainPre == 7) terrain = 4.5 else terrain = 5.0 # difficulty rating if (difficultyPre == 0) difficulty = 1.0 else if (difficultyPre == 1) difficulty = 1.5 else if (difficultyPre == 2) difficulty = 2.0 else if (difficultyPre == 3) difficulty = 2.5 else if (difficultyPre == 4) difficulty = 3.0 else if (difficultyPre == 5) difficulty = 3.5 else if (difficultyPre == 6) difficulty = 4.0 else if (difficultyPre == 7) difficulty = 4.5 else difficulty = 5.0 } function begin_new_entry() { # Beginning of a new entry, reset variables to defaults inrecord = 1 avail = 1 archived = 0 bugs = 0 ifound = 0 iplaced = 0 soc = 0 unfound = 1 tdcnt = 0 gcid = "GC0000" foundt = 0 ifoundrec = 0 ifoundt = 0 container = "unknown" sendgps = 0 # Non-subscription members placer = "" # Bug Fix: FIXME #gctype = "Traditional cache" #type = "regular" #difficulty = 0 #terrain = 0 # End Bug Fix: FIXME if (DEBUG >= 5) print "Begin " NUM " ..." > "/dev/stderr" } function parse_dates(text, cmd, val) { sub("[*]$", "", text) sub("^ *", "", text) # remove leading blanks debug(5, "parse_dates: text=" text) if (text ~ /Today/) { cmd = sprintf("%s -d \"%s\" +%%s", DATE, "12am today") cmd | getline val; close(cmd) } else if (text ~ /Yesterday/) { cmd = sprintf("%s -d \"%s\" +%%s", DATE, "12am yesterday") cmd | getline val; close(cmd) } else if (text ~ /ago/) { cmd = sprintf("%s -d \"12am %s\" +%%s", DATE, text) cmd | getline val; close(cmd) } else if (text ~ /[0-9][^<]*[0-9]/ ) { # GC Format Example Compatible # YYYY/MM/DD 2011/07/13 yes # MM/DD/YYYY 07/13/2011 yes # DD/MM/YYYY 13/07/2011 yes if DATEFMT = 1 # DD/Mmm/YYYY 13/Jul/2001 no # Mmm/DD/YYYY Jul/13/2011 no nf = split(text, fld, "/") if (nf == 3 && DATEFMT == 1) { # DD before MM debug(5, "parse_dates: fld=" fld[1] "." fld[2] "." fld[3]) cmd = sprintf("%s -d \"12am %s\" +%%s", DATE, fld[2] "/" fld[1] "/" fld[3]) cmd | getline val; close(cmd) } else { # Regular way cmd = sprintf("%s -d \"12am %s\" +%%s", DATE, text) cmd | getline val; close(cmd) } } else val = 0 debug(5, "parse_dates: val=" val) return val } BEGIN { q = sprintf("%c", 39) ++NUM gctype = "Traditional cache" type = "regular" } # Test: geo-nearest -s (18) # Test: geo-newest -s (20) # Test: geo-nearest -b multi (8) # # For geo-nearest AND geo-nearest -b /class=".* Data BorderTop"/ { begin_new_entry() debug(3, "Data BorderTop") next } /= 1 && tdcnt <= 10 { if (DEBUG >= 5) print "tdcnt " tdcnt ", text: " $0 > "/dev/stderr" } /]*>", "", name) sub("", "", name) sub(".*", "", name) sub(".*", "", name) sub(".*]*>", "", name) sub("*.", "", name) sub("]*>", "", name) sub("]*>", "", name) sub("<[^>]*>", "", name) sub("<[^>]*>", "", name) debug(5, "name: " name) } # bookmarks by guid=... /]*>", "", name) sub("", "", name) debug(5, "name: " name) gctype = $0 sub(".* alt=.", "", gctype) sub(". />.*", "", gctype) debug(5, "gctype: " gctype) } else { begin_new_entry() gcid = $0 sub(".*]*>", "", gcid) sub("<.*", "", gcid) cid = wp2id(gcid) debug(5, "gcid: " gcid) } } /"Found It!"/ { if (USERFOUND) ifound = 1 next } /Premium Member Only Cache/ { soc = 1 } tdcnt == (9-0) && /[0-9][0-9]*.[0-9][0-9]*/ { # RER: May 4, 2011 date = $0 sub(/^ */, "", date) sub(/ *<.*/, "", date) sub(/\015/, "", date) placedt = parse_dates(date) debug(5, "placedt: " placedt) } # # Yesterday*
# # 3 days ago* # #OR # # Yesterday*
# # # tdcnt == (10-0) && /[a-zA-Z0-9*>]
/ { # catch dates DD MMM YY, N days ago, Today, Yesterday unfound = 0 date = $0 sub(".*", "", date) sub("<.*", "", date) lastfoundt = parse_dates(date) foundt = lastfoundt debug(5, "lastfoundt: " lastfoundt) } tdcnt == (10-0) && /[a-zA-Z0-9*>]<.span>/ { unfound = 0 date = $0 sub(".*Success.>", "", date) sub("<.*", "", date) ifoundt = parse_dates(date) debug(5, "ifoundt: " ifoundt) } / avail = 0; archived = 1 } /<\/strike><\/font/ { # i.e. avail = 0; archived = 1 } /[^<]/ { avail = 0; } /class=".*Strike">/ { avail = 0 } /class=".*Warning Strike.*">/ { avail = 0; archived = 1 } tdcnt == 6 && /^ *by / { placer = $0 sub("^ *by ", "", placer) sub("\015", "", placer) debug(5, "placer: <" placer ">") } tdcnt == 6 && /^ *GC/ { gcid = $0 sub("^ *", "", gcid) sub("\015", "", gcid) debug(5, "GCID: <" gcid ">") cid = wp2id(gcid) } /alt=.Your Geocache/ { # altmy cache # A mistake in the HTML! should be alt="my cache" if (USERFOUND) { iplaced = 1 ifound = 1 } } /alt="Earthcache"/ { type = "earth" gctype = "Earthcache" } /alt="Event Cache"/ { type = "event" gctype = "Event cache" } /alt="Cache In Trash Out Event"/ { type = "cito" gctype = "Cache In Trash Out Event" } /alt="Traditional Cache"/ { type = "regular" gctype = "Traditional cache" } /alt="Letterbox Hybrid"/ { type = "hybrid" gctype = "Letterbox Hybrid" } /alt="Multi-cache"/ { type = "multi" gctype = "Multi-Cache" } /alt="Unknown Cache"/ { type = "unknown" gctype = "Unknown Cache" } /alt="Virtual Cache"/ { type = "virtual" gctype = "Virtual cache" } /alt="Webcam Cache"/ { type = "webcam" gctype = "Webcam Cache" } /alt="Wherigo Cache"/ { type = "wherigo" gctype = "Wherigo Cache" } /alt="Mega-Event Cache"/ { type = "mega" gctype = "Mega-Event Cache" } /name=.CID. / { i = match($0, "value=.") cid = substr($0, i+7, 99) + 0 } /name=.BID. / { i = match($0, "value=.") bid = substr($0, i+7, 99) + 0 } #/ImgGen.seek.CacheInfo.ashx?v=/ { 0 && /[?]v=/ { text = $0 debug(5, "sdt text: " text) sub(".*?v=", "", text) sub(". .*", "", text) debug(5, "sdt text: " text) hash2sdt(text) debug(5, "size: " size " difficulty: " difficulty " terrain: " terrain) container = size } /Unapproved cache/ && inrecord { avail = 0; archived = 1 } /class=.Checkbox NoBolding./ { sendgps = 1 # Subscription members } /<\/[tT][rR]>/ && inrecord { # RER mod 11/22/10: if (0 && .. if (0 && sendgps == 0) next inrecord = 0 debug(5, "End") strtype = "Geocache" if (soc) strtype = strtype "-soc" if (unfound) strtype = strtype "-unfound" else if (ifound) strtype = strtype "-ifound" if (!avail) strtype = strtype "-unavail" if (archived) strtype = strtype "-archived" strtype = strtype "-" type # gpsbabel only allows one time in the DB, figure out what # time to use for this, but always carry all three times # in the .xtra file if (iplaced) ifoundt = placedt vartime=1234 if (VARTIME == "placed") vartime = placedt else if (VARTIME == "ifound") vartime = ifoundt #else if (foundt > 0) vartime = foundt else vartime = placedt # date -d 1970-01-01 1237093200 sec +%Y%m%d # 20090315 cmd = sprintf("%s -d \"1970-01-01 %d sec\" +%%Y%%m%%d", DATE, lastfoundt) cmd | getline lastfound; close(cmd) # avail=1 is the choice right now (8/19/05) # archived=0 is the choice right now (11/14/06) if (!archived && (SOC || !soc)) { if (bid != 0) { printf("-dBID=%d\n", bid) > CIDFILE gcid = id2wp(bid) } else if (cid != 0) { printf("-dCID=%d\n", cid) > CIDFILE } # GCID type vartime ifound soc iplaced tPLACED tFOUND tIFOUND #"%.1f\t%.1f\t%s\t" #difficulty, terrain, container, printf "%s\t%s\t%d\t%s\t%s\t%s\t%d\t%d\t%d\t" \ "%s\t%s\t%s\t%s\n", gcid, strtype, vartime, ifound, soc, iplaced, placedt, foundt, ifoundt, gctype, placer, "hint", lastfound >> XTRAFILE if (--NUM == 0) exit } else if (archived) { if (DEBUG > 5) print "Archived ", gcid, " " name > "/dev/stderr" if (name == "") name = "error-no-name!" if (placer == "") placer = "unknown-placer" # Use "merge" file output, NOT XTRAFILE! printf "%s\t%s\t0.0\t0.0\t%s%s%s\t" \ "%.1f\t%.1f\t%s\t" \ "%s\t%d\t%d\t%d\t%d\t%d\t%d\t%s\t%s\t%s\t%s\t%s\n", gcid, name, "http://www.geocaching.com/seek/cache_details.aspx", "?log=y&wp=", gcid, difficulty, terrain, container, strtype, vartime, ifound, soc, iplaced, placedt, foundt, ifoundt, gctype, placer, "hint", lastfound >> ARCHFILE if (--NUM == 0) exit } } ' } # # A temporary style we can use for merging the loc data with # the scraped html data. This is a dual purpose hack. We # use it as an output format to convert the .loc data to a # record-per-line format. We use it as an input format to # read up the merged data. # make_scrape_style() { cat <<-EOF ENCODING UTF-8 FIELD_DELIMITER TAB RECORD_DELIMITER NEWLINE BADCHARS TAB IFIELD SHORTNAME, "", "%s" IFIELD DESCRIPTION, "", "%s" IFIELD LAT_DECIMAL, "", "%.6f" IFIELD LON_DECIMAL, "", "%.6f" IFIELD URL, "", "%s" IFIELD GEOCACHE_DIFF, "", "%3.1f" #difficulty IFIELD GEOCACHE_TERR, "", "%3.1f" #terrain IFIELD GEOCACHE_CONTAINER,"", "%s" #container (not set) IFIELD ICON_DESCR, "", "%s" #strtype (Geocache-*) IFIELD TIMET_TIME, "", "%ld" #variable time IFIELD IGNORE, "", "%s" #ifound IFIELD IGNORE, "", "%s" #soc IFIELD IGNORE, "", "%s" #iplaced IFIELD IGNORE, "", "%s" #placed time IFIELD IGNORE, "", "%s" #found time IFIELD IGNORE, "", "%s" #ifound time IFIELD GEOCACHE_TYPE, "", "%s" #gc.com type IFIELD GEOCACHE_PLACER, "", "%s" #gc.com placer IFIELD GEOCACHE_HINT, "", "%s" #gc.com hint IFIELD GEOCACHE_LAST_FOUND, "","%s" #gc.com last found OFIELD SHORTNAME, "", "%s" OFIELD DESCRIPTION, "", "%s" OFIELD LAT_DECIMAL, "", "%.6f" OFIELD LON_DECIMAL, "", "%.6f" OFIELD URL, "", "%s" OFIELD GEOCACHE_DIFF, "", "%3.1f" #difficulty OFIELD GEOCACHE_TERR, "", "%3.1f" #terrain OFIELD GEOCACHE_CONTAINER,"", "%s" #container (not set) EOF # OFIELD ICON_DESCR, "", "%s" } # # csv2csv geo-mystery-file # csv2csv() { if [ ! -e "$1" ]; then error "Don't have a -M '$1' file" fi awk -v GEOMYSTERY=$1 ' function latlon ( val ) { if (val ~ ".[.]..*[.].*") { if (val ~ "[-wWsS]") { val = substr(val, 2) neg = 1 } else if (val ~ "[nNeE]") { val = substr(val, 2) neg = 0 } else neg = 0 dd = int(val) sub("[^.]*[.]", "", val) dd += (val+0.0) / 60.0 return neg ? -dd : dd } return val } BEGIN { while (getline 0) { if ($0 ~ "^#") continue if ($0 ~ "^[ ]*$") continue gc=$1 sub(".*/", "", gc) # remove stuff like http://coord.info/ if ($2 ~ "unk") { lat[gc] = 48 lon[gc] = -88 } else { lat[gc] = $2 lon[gc] = $3 } } FS=" " } { if (lat[$1] != 0) { deglat = latlon( lat[$1] ) deglon = latlon( lon[$1] ) # GC# Desc lat lon URL diff terr size printf "%s\t", $1 printf "+%s\t", $2 printf "%.6f\t%.6f\t", deglat, deglon for (i = 5; i < NF; ++i) printf "%s\t", $i printf "%s\n", $NF } else print } ' } # # Fetch the cache patch # gc_fetch_cache_page(){ _page=$1 #out _gcid=$2 #in _url=$3 #in _extra=$4 #in # Fetch the basic cache page echo "" > $_page debug 1 "${_extra}curl $_url #cache fetch $_gcid.html" curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" \ $_url \ | tr -d "\001\007\010\013\017\020\031" \ | sed -e '/<\/html>/d' \ >> $_page size=$(ls -l $_page | awk '{print $5}') if [ $size -lt 1000 ]; then debug 0 "Could not retrieve web page for cache $_gcid" return 1 fi # JSON for logbooks tkn=`grep "userToken = '" $_page | sed -e "s/userToken = '//" -e "s/'.*//" ` jsurl="http://www.geocaching.com/seek/geocache.logbook" jsurl="$jsurl?tkn=$tkn" jsurl="$jsurl&idx=1&num=100&sp=false&sf=false&decrypt=false" debug 1 "curl $jsurl" >&2 curl $CURL_OPTS -s -A "$UA" -b $COOKIE_FILE \ "$jsurl" >> $_page echo "" >> $_page echo "" >> $_page return 0 } # # Query the gc website # gc_query() { if [ $USERFOUND = 0 ]; then FOUND=1 fi if [ $FOUND = 0 ]; then SEARCH="$SEARCH&f=1" fi if [ $DEBUG -gt 0 ]; then TMP=/tmp/geo else TMP=/tmp/geo$$ fi HTMLPAGE=$TMP.page CIDFILE=$TMP.cids LOCFILE=$TMP.loc LOCTMPFILE=$TMP.tmp XTRAFILE=$TMP.xtra CSVFILE=$TMP.csv CSVFILE2=$TMP.csv2 JOINFILE=$TMP.join MERGEFILE=$TMP.merge ARCHFILE=$TMP.arch OUTWAY=$TMP.way STYLE=$TMP.newstyle CRUFT="$CRUFT $HTMLPAGE" CRUFT="$CRUFT $CIDFILE" CRUFT="$CRUFT $LOCFILE" CRUFT="$CRUFT $LOCTMPFILE" CRUFT="$CRUFT $XTRAFILE" CRUFT="$CRUFT $CSVFILE" CRUFT="$CRUFT $CSVFILE2" CRUFT="$CRUFT $JOINFILE" CRUFT="$CRUFT $MERGEFILE" CRUFT="$CRUFT $ARCHFILE" CRUFT="$CRUFT $OUTWAY" CRUFT="$CRUFT $STYLE" if [ $NOCOOKIES = 1 ]; then CRUFT="$CRUFT $COOKIE_FILE" fi # # Login to gc.com # gc_login "$USERNAME" "$PASSWORD" # # Find the bookmark # if [ "$BOOKMARK" != "" ]; then URL="$GEO/bookmarks" debug 1 "$start: curl $URL #bookmark" SEARCH=` curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" "$URL" \ | grep -y ">$BOOKMARK<" \ | $sed \ -e 's@. title.*@@' \ -e 's@^.*href=.http://www.geocaching.com/@@' -e 's/.>.*$//' ` case "$SEARCH" in *bookmarks*) ;; *) error "No bookmark with the name '$BOOKMARK'.";; esac fi # # Find the pocket query # if [ "$POCKETQUERY" != "" ]; then URL="$GEO/pocket/default.aspx" debug 1 "$start: curl $URL #pocket-query" SEARCH=` curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" "$URL" \ | grep -y "title=\"$POCKETQUERY\"" \ | $sed \ -e 's@.*guid=@@' -e 's@".*@@' ` case "$SEARCH" in *-*-*-*-*) SEARCH="?pq=$SEARCH";; *) error "No PQ with the name '$POCKETQUERY'.";; esac fi # # We might combine one or more pages into a single XML, so cobble # up a header with the ?xml and loc tags. # cat <<-EOF > $LOCFILE EOF # # Loop, getting at least "NUM" locations # ((NUM=NUM-1)) if [ $DEBUG -gt 0 ]; then filter2="tee $TMP.bulk" else filter2=cat fi subscriber=1 > $XTRAFILE > $ARCHFILE ((start=0)) while ((start <= NUM)); do sleep $GEOSLEEP # # Fetch the page of closest caches and scrape the cache ID's # case "$SEARCH" in *bookmark*) URL="$GEO/$SEARCH" ;; *) URL="$GEO/seek/nearest.aspx" URL="$URL$SEARCH" ;; esac debug 1 "$start: curl $URL #list" if ((start > 0)); then # "postback"... grab the "next" button case "$SEARCH" in *bookmark*) __EVENTTARGET="ListInfo\$pgrBMItems\$_ctl8" TGT=$($sed -n "s/^.*__doPostBack('.*pgrBMItems\$\(.*\)','.*/\1/p" \ < $HTMLPAGE) if [ "$TGT" = "" ]; then error "TGT is blank!" fi __EVENTTARGET="ctl00%24ContentBody%24ListInfo%24pgrBMItems%24$TGT" ;; *) TGT=$($sed -n "s/^.*__doPostBack('.*pgrTop\$\(.*\)','.*/\1/p" \ < $HTMLPAGE) if [ "$TGT" = "" ]; then error "TGT is blank!" fi __EVENTTARGET="ctl00%24ContentBody%24pgrTop%24$TGT" ;; esac curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" \ -d __EVENTTARGET="$__EVENTTARGET" \ $viewstate \ "$URL" \ | $sed -e "s/'/'/g" -e "s/\r//" > $HTMLPAGE else curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" \ "$URL" \ | $sed -e "s/'/'/g" -e "s/\r//" > $HTMLPAGE if [ "$DEBUG" -ge 1 ]; then grep "Total Records:.*Top.*" $HTMLPAGE | sed -e "s/<.b>.*//" -e "s/^.*span>//" -e "s///" 1>&2 fi fi rc=$?; if [ $rc != 0 ]; then error "curl: fetch $URL" fi if grep -s -q "We encountered an error when requesting that page!" \ $HTMLPAGE; then error "searching error (1) on $start" fi if grep -s -q "has resulted in an error" \ $HTMLPAGE; then error "searching error (2) on $start" fi if grep -s -q "By State" $HTMLPAGE; then error "searching gave up on $start" fi if grep -s -q ">Advanced Search<" $HTMLPAGE; then error "need a country AND a state!" fi # # Grab a few important values from the page # gc_getviewstate $HTMLPAGE # # Grab the CIDs into two categories: found and notfound # > $CIDFILE debug 3 "getcids $HTMLPAGE $CIDFILE $XTRAFILE $ARCHFILE $((NUM-start))" getcids $HTMLPAGE $CIDFILE $XTRAFILE $ARCHFILE $((NUM-start)) # # Fetch the waypoints, rip out the ?xml and loc tags, and # append to the $LOCFILE file. # if [ -s "$CIDFILE" ]; then sleep $GEOSLEEP case "$SEARCH" in *bookmark*) URL="$GEO/$SEARCH" ;; *) URL="$GEO/seek/nearest.aspx" URL="$URL$SEARCH" ;; esac # # Fetch the .loc file # 1) -d "Download=Download+Waypoints"... geo-nearest # 2) -d "ListInfo:btnDownload= ... old # 3) -d 'ctl00$ContentBody ... -b acro # debug 2 "$start: curl $URL #loc" curl $CURL_OPTS -s -b $COOKIE_FILE -A "$UA" \ $viewstate \ `cat $CIDFILE` \ -d "Download=Download+Waypoints" \ -d "ListInfo:btnDownload=Download+to+.Loc" \ -d 'ctl00$ContentBody$ListInfo$btnDownload=Download+to+.Loc' \ "$URL" \ | $filter2 \ | $sed -e 's/^]*>//' \ -e 's/>[gG]eocacheGeocache]*>//' \ -e 's###' \ > $LOCTMPFILE rc=$?; if [ $rc != 0 ]; then error "curl: fetch the waypoints" fi if grep -s -q "you are not logged in" $LOCTMPFILE; then error "you are not logged in on $start" fi if grep -s -q "has resulted in an error" $LOCTMPFILE; then error "searching error (3) on $start" fi if grep -s -q "Geocaching > Search for Geocaches" $LOCTMPFILE; then error "searching error (4) on $start" fi if grep -s -q "recaptcha_challenge_field" $LOCTMPFILE; then # # Basic members: do it the SLOW way # if [ "$GEODIR" != "" -a ! -d "$GEODIR" ]; then mkdir "$GEODIR" || error "Couldn't mkdir $GEODIR" fi if [ "$GEODIR/caches" != "" -a ! -d "$GEODIR/caches" ]; then mkdir "$GEODIR/caches" \ || error "Couldn't mkdir $GEODIR/caches" fi if [ $subscriber = 1 ]; then debug 0 "Basic Member: pay the \$30/yr fee for Premium Member!" debug 0 "Basic Member: doing it the REAL SLOW way!!!" timestamp="$GEODIR/caches/.timestamp" $touch -d "1 day ago" $timestamp fi subscriber=0 # # Pull 20 GCIDs... # bstart=$start grep "^ *GC.*" $HTMLPAGE \ | $sed -e "s/ //g" \ | while read gcid; do # # Get the cache page # cachepage="$GEODIR/caches/$gcid.html" if [ ! -s $cachepage -o $timestamp -nt $cachepage ]; then # cache page doesn't exist or out of date sleep 3 #$GEOSLEEP urlpage="http://www.geocaching.com" urlpage="$urlpage/seek/cache_details.aspx" urlpage="$urlpage?log=y&wp=$gcid" gc_fetch_cache_page $cachepage $gcid $urlpage \ "$bstart: " if [ $? != 0 ]; then continue fi fi # 01/07/12: remove soc's! if grep -q 'alt="Premium Members only"' $cachepage; then continue fi # # Cobble up the .loc file entry # name=` grep -A1 "" $cachepage \ | tail -1 | tr -d "\r" \ | $sed -e 's/[ ]*GC[^ ]* //' -e 's/ (.*by/ by/' ` diff=` grep ctl00_ContentBody_uxLegendScale $cachepage \ | $sed -e 's/.*alt="//' -e 's/ .*//' ` terr=` grep ctl00_ContentBody_Localize6 $cachepage \ | $sed -e 's/.*alt="//' -e 's/ .*//' ` size=` grep "alt=.Size:" $cachepage \ | $sed -e 's/.*alt="Size: //' -e 's/" .*//' ` case $size in Unknown) cont=1;; Micro) cont=2;; Regular) cont=3;; Large) cont=4;; Virtual) cont=5;; Other) cont=6;; Small) cont=8;; *) cont=1;; esac echo "<waypoint>" echo "<name id=\"$gcid\"><![CDATA[$name]]></name>" grep "lnkConversions" $cachepage \ | $sed -e 's/.*lat=/<coord lat="/' \ -e 's/&lon=/" lon="/' -e 's@&.*@"/>@' echo "<type>Geocache</type>" echo -n "<link text=\"Cache Details\">" urlpage="http://www.geocaching.com" urlpage="$urlpage/seek/cache_details.aspx" urlpage="$urlpage?wp=$gcid" echo -n "$urlpage" echo "</link>" echo "<difficulty>$diff</difficulty>" echo "<terrain>$terr</terrain>" echo "<container>$cont</container>" echo "</waypoint>" debug 3 "bstart: $bstart" if [ $bstart == $NUM ]; then break fi ((++bstart)) #break done >> $LOCFILE else cat $LOCTMPFILE >> $LOCFILE fi fi # # Check to see if the user hasn't agreed to license terms # if grep -s -q "lblAgreementText" $LOCFILE; then easy_warning >&2 remove_cruft exit fi ((start=start+20)) # If the Next button is disabled, break this loop # grep "Records: <b>[1-9].*disabled.><b>Next<" $HTMLPAGE if grep -s -q "Records: <b>[1-9].*disabled.><b>Next " $HTMLPAGE; then # echo "$start: dis" break; fi done # # Finish off the .loc file # echo "</loc>" >> $LOCFILE # # Convert the .loc data to .csv format and join it with # the extra data scraped from the HTML page. Filter out # the data according to the -I and -X options. # # http://www.geocaching.com/seek/cache_details.aspx?wp=GCG2H4 # http://www.geocaching.com/seek/cache_details.aspx?log=y&wp=GCG2H4 # http://www.geocaching.com/seek/cache_details.aspx?ID=92117&log=y # # The joined .csv format looks like this: # GCH636 Jidana 3 by rickrich 44.94520 -93.47540 \ # http://www.geocaching.com/seek/cache_details.aspx?log=y&wp=GCH636 \ # Geocache-ifound-regular 1070285077 1 0 1 \ # 1067925600 1070285077 0 # make_scrape_style > $STYLE dbgcmd gpsbabel -i geo$GEONUKE -f $LOCFILE \ -o xcsv,style=$STYLE -F $CSVFILE2 if [ $? != 0 ]; then cp $LOCFILE /tmp/geo.err error "gpsbabel returned error code [1]" fi # Convert CSV into CSV with puzzles... csv2csv $GEOMYSTERY < $CSVFILE2 > $CSVFILE # 01/07/12: NO --nocheck-order; it is wrong! join -t ' ' $CSVFILE $XTRAFILE > $JOINFILE if [ $? != 0 ]; then cp $CSVFILE /tmp/geo.err.csv cp $XTRAFILE /tmp/geo.err.xtra error "joined file error: see join /tmp/geo.err.{csv,xtra}" fi egrep -- "$INCLUDE" < $JOINFILE \ | egrep -v -- "$EXCLUDE" \ | $sed -e 's/wp=/log=y\&&/' > $MERGEFILE if [ $FOUND = 1 ]; then cat $ARCHFILE \ | egrep -- "$INCLUDE" | egrep -v -- "$EXCLUDE" \ | $sed -e 's/wp=/log=y\&&/' >> $MERGEFILE fi if [ $DEBUG -ge 2 ]; then # First two of these should be the same number of lines! wc -l $CSVFILE >&2 wc -l $XTRAFILE >&2 wc -l $MERGEFILE >&2 fi # # Convert to the desired format # BABELFILT= if [ "$RADIUS" != "" ]; then BABELFILT="-x radius,distance=$RADIUS,lat=$LAT,lon=$LON" fi if [ $SQL = 1 ]; then # # add it via mysql # if [ "$OUTFILE" != "" ]; then >"$OUTFILE" fi if [ $PURGE = 1 ]; then gpsdrive_purge | gpsdrive_mysql PURGE=2 fi dbgcmd gpsbabel $BABELFLAGS \ -i xcsv,style=$STYLE -f $MERGEFILE \ $BABELFILT -o "$OUTFMT" -F $OUTWAY if [ $? != 0 ]; then error "gpsbabel returned error code [2]" fi gpsdrive_add <$OUTWAY $SQLTAG | gpsdrive_mysql elif [ $MAP = 1 ]; then dbgcmd gpsbabel $BABELFLAGS \ -i xcsv,style=$STYLE -f $MERGEFILE \ $BABELFILT -o "$OUTFMT" -F $OUTWAY if [ $? != 0 ]; then error "gpsbabel returned error code [3]" fi if [ "$OUTFILE" = "" ]; then dbgcmd geo-map -s0 $MAPOPTS -t$OUTWAY else dbgcmd geo-map -s0 $MAPOPTS -t$OUTWAY -o"$OUTFILE" fi else # # output to stdout or to a file # if [ "$OUTFILE" = "" ]; then OUTTMP="$TMP.way"; CRUFT="$CRUFT $OUTTMP" dbgcmd gpsbabel $BABELFLAGS \ -i xcsv,style=$STYLE -f $MERGEFILE \ $BABELFILT -o "$OUTFMT" -F $OUTTMP if [ $? != 0 ]; then error "gpsbabel returned error code [4]" fi cat $OUTTMP else dbgcmd gpsbabel $BABELFLAGS \ -i xcsv,style=$STYLE -f $MERGEFILE \ $BABELFILT -o "$OUTFMT" -F $OUTFILE if [ $? != 0 ]; then error "gpsbabel returned error code [5]" fi fi fi # # Optionally, print the HTML pages # if [ "$CMDPIPE" != "" ]; then OIFS="$IFS" IFS=" " while read id desc lat lon url diff terr container strtype \ vartime ifound soc iplaced placedt foundt ifoundt extra; do url="$url&decrypt=y" echo "Print: $url" HTMLPAGE2=$TMP.html CRUFT="$CRUFT $HTMLPAGE2" debug 1 "curl $url" >&2 dbgcmd curl $CURL_OPTS -s -A "$UA" -b $COOKIE_FILE "$url" > $HTMLPAGE2 htmldoc --quiet -t ps --nup 2 --fontsize 14 --webpage $HTMLPAGE2 \ | psselect -q -p1-1 | eval $CMDPIPE # exit done < $MERGEFILE IFS="$OIFS" fi # # Optionally, fetch printable HTML pages # if [ "$HTMLDIR" != "" -o "$LOGDIR" != "" ]; then if [ "$HTMLDIR" != "" -a ! -d "$HTMLDIR" ]; then mkdir "$HTMLDIR" || error "Couldn't mkdir $HTMLDIR" fi if [ "$LOGDIR" != "" -a ! -d "$LOGDIR" ]; then mkdir "$LOGDIR" || error "Couldn't mkdir $LOGDIR" fi HTMLPAGE2=$TMP.html CRUFT="$CRUFT $HTMLPAGE2" TIMESTAMP=$TMP.time CRUFT="$CRUFT $TIMESTAMP" fetchcnt=0 fetchmax=1000 if [ $DEBUG -ge 3 ]; then fetchmax=3 fi OIFS="$IFS" IFS=" " while read id desc lat lon url diff terr container strtype \ vartime ifound soc iplaced placedt foundt ifoundt extra; do # # Don't fetch page if we already have a current version # #debug 1 "placedt=<$placedt> <$foundt>" if [ $placedt -gt $foundt ]; then filetime="$placedt" else filetime="$foundt" fi $touch -d "1/1/70 $filetime seconds last second" $TIMESTAMP if [ "$filetime" -gt 0 -a "$HTMLDIR/$id.html" -nt $TIMESTAMP ]; then continue fi # Basic member... if [ "$subscriber" == 0 -a "$HTMLDIR" != "" ]; then debug 2 "cp $GEODIR/caches/$id.html $HTMLDIR/$id.html" cp "$GEODIR/caches/$id.html" "$HTMLDIR/$id.html" # debug 2 "f: $filetime" if [ "$filetime" -gt 0 ]; then $touch -d "1/1/70 $filetime seconds" "$HTMLDIR/$id.html" fi continue fi # Limit to 1000 caches/day ((fetchcnt=fetchcnt+1)) if [ $fetchcnt -gt $fetchmax ]; then error "Fetch count exceeded $fetchmax. Try tomorrow!" fi # Be kind to the server. Do not remove this sleep sleep $GEOSLEEP gc_fetch_cache_page $HTMLPAGE $id $url "" if [ $? != 0 ]; then continue fi if [ "$HTMLDIR" != "" ]; then cp $HTMLPAGE "$HTMLDIR/$id.html" || error "Couldn't copy $id cache page" if [ "$filetime" -gt 0 ]; then $touch -d "1/1/70 $filetime seconds" "$HTMLDIR/$id.html" fi fi if [ "$LOGDIR" != "" ]; then $sed -e '1,/Logged Visits/d' \ -e 's/<strong><img src=/\ &/g' \ < $HTMLPAGE | egrep ">$LOGUSERNAME<|strong> \($LOGUSERNAME\) \(" | $sed -e 's#<a href="log.aspx?LUID.*##' \ -e 's#<a href=./profile[^ ]*##' \ > $HTMLPAGE2 lynx -dump $HTMLPAGE2 > $LOGDIR/$id.log if [ "$filetime" -gt 0 ]; then $touch -d "1/1/70 $filetime seconds" "$LOGDIR/$id.log" fi fi done < $MERGEFILE IFS="$OIFS" if [ "$LOGDIR" != "" ]; then # This is a hack, and might be inaccurate echo -n "Finds:" >&2 MONTHS=" January | February | March | April | May | June " MONTHS="$MONTHS| July | August | September | October " MONTHS="$MONTHS| November | December " egrep "$MONTHS" $LOGDIR/*.log | egrep "Found it |icon_smile|icon_happy|icon_camera" | wc -l >&2 fi fi } ############################################################################## # end #include "geo-common-gc" ############################################################################## ############################################################################## # begin #include "geo-common-gpsdrive" ############################################################################## # # default MySQL global options... # SQLUSER=gast SQLPASS=gast SQLDB=geoinfo SQLITEDB=$HOME/.gpsdrive/waypoints.db SQLTAG=Geocache # # procedures for updating gpsdrive database via MySQL # # Global Vars: $SQLDB, $SQLTAG $OUTFILE # gpsdrive_create_210() { echo "CREATE TABLE poi (" echo "poi_id INTEGER PRIMARY KEY AUTOINCREMENT," echo "name VARCHAR(80) NOT NULL default 'not specified'," echo "poi_type VARCHAR(160) NOT NULL default 'unknown'," echo "lat DOUBLE NOT NULL default '0'," echo "lon DOUBLE NOT NULL default '0'," echo "alt DOUBLE default '0'," echo "comment VARCHAR(255) default NULL," echo "last_modified DATETIME NOT NULL default '0000-00-00'," echo "source_id INTEGER NOT NULL default '1'," echo "private CHAR(1) default NULL);" echo "CREATE TABLE poi_extra (" echo "poi_id INTEGER NOT NULL default '0'," echo "field_name VARCHAR(160) NOT NULL default '0'," echo "entry VARCHAR(8192) default NULL);" } gpsdrive_purge() { case "$GPSDRIVE_VER" in ""|"2.09") delcmd="delete from waypoints" echo "use $SQLDB;" echo "$delcmd where type like '$SQLTAG%';" ;; "2.10") if [ ! -s $SQLITEDB ]; then gpsdrive_create_210 fi SQLTAG=`echo $SQLTAG | tr A-Z a-z` delcmd="delete from poi" echo "$delcmd where poi_type like '$SQLTAG%';" ;; esac } gpsdrive_add_209() { delcmd="delete from waypoints" addcmd="replace into waypoints (name,lat,lon,type)" addcmd="insert into waypoints (name,lat,lon,type)" sqltag="$1" echo "use $SQLDB;" while read name lat lon type extra do name=`echo "$name" | tr -d "'"` # Primary key is autoincrementing id number, so delete # the old record (if any) by name and type if [ $PURGE = 0 ]; then echo "$delcmd where name='$name' and type like '$SQLTAG%';" fi if [ $DELETE = 0 ]; then # Add the new record if [ "$sqltag" = "Geocache" ]; then tag="$type" else tag="$sqltag" fi echo "$addcmd values ('$name','$lat','$lon','$tag');" fi done } gpsdrive_add_210(){ if [ ! -s $SQLITEDB ]; then gpsdrive_create_210 fi delcmd="delete from poi" addcmd="replace into poi (name,poi_type,lat,lon,alt,comment,last_modified)" addcmd="insert into poi (name,poi_type,lat,lon,alt,comment,last_modified)" sqltag="$1" sqltag=`echo "$sqltag" | tr A-Z a-z` OIFS="$IFS" IFS="|" #while read name lat lon type extra poi_id=0 egrep -v 'Geocache Found|-ifound' \ | tr -d "|" | tr ' ' '|' | tr -d "'" | while read index shortname description notes url urltext icon lat lon \ lat32 lon32 latdecdir londecdir latdirdec londirdec latdir londir \ altfeet altmeters excel timet diff terr container type \ pathmiles pathkm placer yyyymmmdd hint lastfound extra do if [ "$placer" = "$USERNAME" ]; then continue fi if [ "$placer" = "dyl1231" ]; then continue fi #name=`echo "$description" | tr -d "'"` #For Performance... name=${description//\'/} # Primary key is autoincrementing id number, so delete # the old record (if any) by name and type if [ $PURGE = 0 ]; then echo "$delcmd where name='$name' and poi_type like '%$sqltag%';" fi ((poi_id=poi_id+1)) if [ $DELETE = 0 ]; then # Add the new record if [ "$sqltag" = "geocache" ]; then tag="$type" else tag="$sqltag" fi case "$type" in "Earthcache") poi_type="geocache.geocache_earth";; "Event Cache") poi_type="geocache.geocache_event";; "Mega-Event Cache") poi_type="geocache.geocache_event";; "Cache In Trash Out Event") poi_type="geocache.geocache_event";; "found") poi_type="geocache.geocache_found";; "Multi-cache") poi_type="geocache.geocache_multi";; "Unknown Cache") poi_type="geocache.geocache_mystery";; "night") poi_type="geocache.geocache_night";; "Traditional Cache") poi_type="geocache.geocache_traditional";; "Virtual Cache") poi_type="geocache.geocache_virtual";; "Webcam Cache") poi_type="geocache.geocache_webcam";; *) poi_type="geocache";; esac echo -n "$addcmd values ('$name','$poi_type'," echo -n "'$lat','$lon'," echo -n "'0.0'," #alt echo -n "'$type $container $diff/$terr. Last Found: $lastfound. $hint'," echo "'0');" fi done IFS="$OIFS" } gpsdrive_add() { case "$GPSDRIVE_VER" in ""|"2.09") gpsdrive_add_209 "$1";; "2.10") gpsdrive_add_210 "$1";; esac } gpsdrive_mysql() { if [ "$OUTFILE" != "" ]; then cat >> $OUTFILE elif [ $DEBUG -gt 0 ]; then cat else mysql -u$SQLUSER -p$SQLPASS fi } gpsdrive_sqlite3() { if [ "$OUTFILE" != "" ]; then cat >> $OUTFILE elif [ $DEBUG -gt 0 ]; then cat else sqlite3 $HOME/.gpsdrive/waypoints.db fi } # # Extended list of gpsbabel output formats # gpsbabel_formats() { gpsbabel -? | sed -e '1,/File Types/d' -e '/Supported data filters/,$d' echo " gpsdrive.sql " \ "GpsDrive direct MySQL database insertion" echo " map[,geo-map-opts] " \ "Display map of waypoints using geo-map" } ############################################################################## # end #include "geo-common-gpsdrive" ############################################################################## gid2id() { gid="${1/#GC/}" if [ "$gid" "<" "G000" ]; then echo "$((0x$gid))" else ((val=0)) ((pos=0)) while ((pos < 4)); do digit=`expr index 0123456789ABCDEFGHJKMNPQRTVWXYZ "${gid:$pos:1}"` ((val=val*31+$digit-1)) ((++pos)) done echo "$((val-=411120))" fi } id2gid() { awk -v id="$1" ' BEGIN { gid = ""; if (id < 0) ; else if (id < 65536) gid = sprintf("GC%04X", id) else { GcOffset = 16 * 31 * 31 * 31 - 65536 GcSet = "0123456789ABCDEFGHJKMNPQRTVWXYZ" id += GcOffset; for (i = 1; i <= 4; ++i) { gid = substr(GcSet, id%31 + 1, 1) gid id = int(id / 31) } if (id) gid = "" else gid = "GC" gid } print gid } ' } # # Query the gc website # gc_query_init() { if [ $DEBUG -gt 0 ]; then TMP=/tmp/geo else TMP=/tmp/geo$$ fi HTMLPAGE=$TMP.page CIDFILE=$TMP.cids LOCFILE=$TMP.loc LOCFILE=/tmp/geo-soon.loc; rm -f $LOCFILE PIPEFILE=$TMP.ps TSFILE=$TMP.ts LOCTMP=$TMP.loctmp OUTWAY=$TMP.way CRUFT="$CRUFT $HTMLPAGE" CRUFT="$CRUFT $CIDFILE" #CRUFT="$CRUFT $LOCFILE" CRUFT="$CRUFT $LOCTMP" CRUFT="$CRUFT $TSFILE" CRUFT="$CRUFT $PIPEFILE" CRUFT="$CRUFT $OUTWAY" if [ $NOCOOKIES = 1 ]; then CRUFT="$CRUFT $COOKIE_FILE" fi # # Login to gc.com # gc_login "$USERNAME" "$PASSWORD" } test_cid() { _id=$1 debug 1 "lo=$lo hi=$hi test=$1" # # Grab a few important values from the page # get_value __EVENTTARGET $HTMLPAGE get_value __EVENTARGUMENT $HTMLPAGE gc_getviewstate $HTMLPAGE sleep 2 dbgcmd curl $CURL_OPTS -s -b $COOKIE_FILE -A "$UA" \ -d __EVENTTARGET="$__EVENTTARGET" \ -d __EVENTARGUMENT="$__EVENTARGUMENT" \ $viewstate \ -d CID=$_id \ -d "Download=Download+Waypoints" \ "$URL" \ > $LOCTMP read hdr < $LOCTMP case "$hdr" in *html*) return 1;; *) return 0;; esac } gc_query_last() { lo=$1 hi=$2 logid=$(id2gid $lo) higid=$(id2gid $hi) debug 0 "Search for last submitted cache between $lo-$hi ($logid-$higid)" URL="$GEO/seek/nearest.aspx" URL="$URL$SEARCH" dbgcmd curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" \ "$URL" > $HTMLPAGE while : do if [ $hi -le $lo ]; then break fi cid=$(dc -e "$hi $lo +2/p") if test_cid $cid; then # ID exists lo=$(dc -e "$cid 1+p") else # ID doesn't exist hi=$(dc -e "$cid 1-p") fi done LASTID=$lo debug 0 "Last submitted cache is $LASTID ($(id2gid $LASTID))" } gc_gid_query() { # # We might combine one or more pages into a single XML, so cobble # up a header with the ?xml and loc tags. # cat <<-EOF > $LOCFILE <?xml version="1.0" encoding="UTF-8"?> <loc version="1.0" src="EasyGPS"> EOF sleep 3 URL="$GEO/seek/nearest.aspx" URL="$URL$SEARCH" dbgcmd curl $CURL_OPTS -L -s -b $COOKIE_FILE -A "$UA" \ "$URL" > $HTMLPAGE ((qcnt=(IDCNT+19)/20)) ((q=0)) ((i=0)) while ((q < qcnt)); do > $CIDFILE while ((i < IDCNT)); do id=${ID[i]} echo "-dCID=$id" >> $CIDFILE ((++i)) if ((i%20 == 0)); then break; fi done ((++q)) # # Grab a few important values from the page # get_value __EVENTTARGET $HTMLPAGE get_value __EVENTARGUMENT $HTMLPAGE gc_viewstate $HTMLPAGE sleep 2 dbgcmd curl $CURL_OPTS -s -b $COOKIE_FILE -A "$UA" \ -d __EVENTTARGET="$__EVENTTARGET" \ -d __EVENTARGUMENT="$__EVENTARGUMENT" \ $viewstate \ `cat $CIDFILE` \ -d "Download=Download+Waypoints" \ "$URL" \ | sed -e 's/^<?xml [^>]*>//' \ -e 's/>[gG]eocache</>Geocache</g' \ -e 's/<loc [^>]*>//' \ -e 's#</loc>##' \ | tr '\303' 'A' \ > $LOCTMP read hdr < $LOCTMP case "$hdr" in *html*) debug 0 "Last ID was $id ($(id2gid $id))" echo "LASTID=$id" > $HOME/.geo-soon break; ;; *) cat $LOCTMP >> $LOCFILE ;; esac # # Check to see if the user hasn't agreed to license terms # if grep -s -q "STEP2=NO" $LOCFILE; then easy_warning >&2 remove_cruft exit fi done # # Finish off the .loc file # echo "</loc>" >> $LOCFILE # # Filter to our radius and convert to pipesep format # BABELFILT= if [ "$RADIUS" != "" ]; then BABELFILT="-x radius,distance=$RADIUS,lat=$LAT,lon=$LON" fi dbgcmd gpsbabel $BABELFLAGS \ -i geo$GEONUKE -f $LOCFILE \ $BABELFILT -o tabsep -F- | tr ' ' '|' > $PIPEFILE BABELFILT= # # Fetch each cache page to see if it exists # OIFS="$IFS" IFS="|" while read index shortname description notes url urltext icon lat lon \ lat32 lon32 latdecdir londecdir latdirdec londirdec latdir londir \ altfeet altmeters excel timet diff terr container type extra; do #url="http://www.geocaching.com/seek/cache_details.aspx?wp=GCJMA5" sleep 1 dbgcmd curl $CURL_OPTS -s -A "$UA" "$url" > $HTMLPAGE msg="This cache listing has not been approved yet" if grep -q "$msg" $HTMLPAGE; then echo -e "$index \c" echo -e "$shortname \c" echo -e "$description \c" echo -e "$notes \c" echo -e "$url \c" echo -e "$urltext \c" echo -e "$icon \c" echo -e "$lat \c" echo -e "$lon \c" echo fi done < $PIPEFILE > $TSFILE IFS="$OIFS" # # Convert to the desired format # if [ $SQL = 1 ]; then # # add it via mysql # if [ "$OUTFILE" != "" ]; then >"$OUTFILE" fi if [ $PURGE = 1 ]; then gpsdrive_purge | gpsdrive_mysql PURGE=2 fi dbgcmd gpsbabel $BABELFLAGS \ -i tabsep -f $TSFILE \ $BABELFILT -o "$OUTFMT" -F $OUTWAY gpsdrive_add <$OUTWAY $SQLTAG | gpsdrive_mysql elif [ $MAP = 1 ]; then dbgcmd gpsbabel $BABELFLAGS \ -i tabsep -f $TSFILE \ $BABELFILT -o "$OUTFMT" -F $OUTWAY if [ "$OUTFILE" = "" ]; then dbgcmd geo-map -s0 $MAPOPTS -t$OUTWAY else dbgcmd geo-map -s0 $MAPOPTS -t$OUTWAY -o"$OUTFILE" fi else # # output to stdout or to a file # if [ "$OUTFILE" = "" ]; then OUTFILE=/dev/fd/1 fi dbgcmd gpsbabel $BABELFLAGS \ -i tabsep -f $TSFILE \ $BABELFILT -o "$OUTFMT" -F $OUTFILE fi } # # Set default options, can be overriden on command line or in rc file # UPDATE_URL=$WEBHOME/geo-nearest UPDATE_FILE=geo-nearest.new read_rc_file # # Process the options # SQLTAG=Geocache-soon RADIUS=35 NUM=1000 STARTID= gc_getopts "$@" shift $? # # Main program # case "$#" in 6) # Cut and paste from geocaching.com cache page # N 44° 58.630 W 093° 09.310 LAT=`echo "$1$2.$3" | tr -d '\260\302' ` LAT=`latlon $LAT` LON=`echo "$4$5.$6" | tr -d '\260\302' ` LON=`latlon $LON` SEARCH="?origin_lat=$LAT&origin_long=$LON" ;; 2) LAT=`latlon $1` LON=`latlon $2` SEARCH="?origin_lat=$LAT&origin_long=$LON" ;; 0) SEARCH="?origin_lat=$LAT&origin_long=$LON" ;; *) usage ;; esac # # Init vars and get a viewstate # gc_query_init # # Figure out where to start search from. Cache the last ID in # a file. # LASTSOON=$HOME/.geo-soon if [ ! -f $LASTSOON ]; then $touch -d "1/1/70" $LASTSOON fi TIMESTAMP=${TMP}-timestamp; CRUFT="$CRUFT $TIMESTAMP" $touch -d "120 minutes ago" $TIMESTAMP . $LASTSOON if [ $LASTSOON -ot $TIMESTAMP ]; then if [ "$LASTID" = "" ]; then LASTID=200000 fi ((LASTID=LASTID-1)) gc_query_last $LASTID 220000 echo "LASTID=$LASTID" > $LASTSOON fi ((STARTID=LASTID-NUM)) debug 0 "Starting search from $LASTID-$NUM=$STARTID ($(id2gid $STARTID))" id="$STARTID" while ((i < NUM)); do ((idn=id+i)) ID[$i]=$idn ((++i)) done IDCNT=$i gc_gid_query