Created
January 11, 2012 20:31
-
-
Save gausie/1596609 to your computer and use it in GitHub Desktop.
GeoCaching Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Written during a Maths lecture by Samuel Gaus | |
*/ | |
class GeoCaching { | |
private $hash; | |
private $cookie_file; | |
private $username; | |
private $password; | |
private $credentials = false; | |
public function __construct(){ | |
@session_start(); | |
$_SESSION['gc_hash'] = $this->hash = (isset($_SESSION['gc_hash']))?$_SESSION['gc_hash']:md5(time()); | |
$this->cookie_file = "./cookies/{$this->hash}.txt"; | |
} | |
private function postGet($url,$postData=null,$referer=null){ | |
if(!isset($referer)){ | |
$referer = $url; | |
} | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); | |
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
if(isset($postData) && !empty($postData)){ | |
curl_setopt($ch, CURLOPT_POST, TRUE); | |
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); | |
} | |
curl_setopt($ch, CURLOPT_COOKIEJAR, $this->cookie_file); | |
curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie_file); | |
curl_setopt($ch, CURLOPT_REFERER, $referer); | |
return curl_exec($ch); | |
} | |
public function login($user,$pass){ | |
$this->credentials = true; | |
$this->username = $user; | |
$this->password = $pass; | |
} | |
public function loginWAP($user=null,$pass=null){ | |
// Fix the mistake I keep making. | |
if(isset($user) && isset($pass)){ | |
$this->login($user,$pass); | |
}elseif(!$this->credentials){ | |
throw new Exception("You must supply GC login credentials to use this command."); | |
} | |
//todo Maybe save the login status to the cookie file. | |
if(isset($_SESSION['gc_loggedin_wap'])){ | |
return true; | |
} | |
$url = "http://wap.geocaching.com/login.aspx"; | |
$data = $this->postGet($url); | |
extract($this->getUFPSandViewstate($data)); | |
//Log in! | |
$postData = array( | |
"__VIEWSTATE" => $vs, | |
"__EVENTTARGET" => "", | |
"__EVENTARGUMENT" => "", | |
"txtUsername" => $this->username, | |
"txtPassword" => $this->password, | |
"cmdLogin" => "Submit" | |
); | |
$data = $this->postGet("{$url}?__ufps={$ufps}",$postData,$url); | |
// Check success | |
if(preg_match("/<title>Error Page<\/title>/i", $data)){ | |
//throw new Exception('Incorrect username and/or password.'); | |
}else{ | |
$_SESSION['gc_loggedin_wap'] = true; | |
return true; | |
} | |
} | |
private function getUFPSandViewstate($data){ | |
if(!preg_match('/<form .*? action=".*?\.aspx\?__ufps=([0-9]*)">/i', $data, $regs1)){ | |
throw new Exception ("UFPS string not found in regex."); | |
} | |
if(!preg_match('/__VIEWSTATE" value="(.*)"/i', $data, $regs2)){ | |
throw new Exception ("Viewstate string not found in regex."); | |
} | |
return array( | |
"ufps" => $regs1[1], | |
"vs" => $regs2[1] | |
); | |
} | |
public function getCacheDetails($gccode){ | |
try { | |
$this->loginWAP(); | |
} catch (Exception $e) { | |
throw $e; | |
} | |
// Grab initial ASP session data | |
$url = "http://wap.geocaching.com/default.aspx"; | |
extract($this->getUFPSandViewstate($this->postGet($url))); | |
// Go to search page | |
$postData = array( | |
"__EVENTTARGET" => "lnkViewCache", | |
"__EVENTARGUMENT" => "frmEnterWpt", | |
"__VIEWSTATE" => $vs | |
); | |
$searchurl = "{$url}?__ufps={$ufps}"; | |
$data = $this->postGet($searchurl,$postData,$url); | |
extract($this->getUFPSandViewstate($data)); | |
// Make the search | |
$postData = array( | |
"__VIEWSTATE" => $vs, | |
"__EVENTTARGET" => "", | |
"__EVENTARGUMENT" => "", | |
"txtEnterWpt" => $gccode, | |
"cmdEnterWpt" => "Submit" | |
); | |
$cacheurl = "{$url}?__ufps={$ufps}"; | |
$data = $this->postGet($cacheurl,$postData,$searchurl); | |
preg_match("/\s(.*?)<br>\s+{$gccode}/i", $data, $regs); $name = $regs[1]; | |
preg_match("/\sOwner: (.*?)<br>/i", $data, $regs); $owner = $regs[1]; | |
preg_match('/\s((N|S) (.*?))\s*<br>/i', $data, $regs); $lat = str_replace("°","",$regs[1]); | |
preg_match('/\s((W|E) (.*?))\s*<br>/i', $data, $regs); $lng = str_replace("°","",$regs[1]); | |
return array( | |
"name" => $name, | |
"owner" => $owner, | |
"lat" => $this->minDectoDecDegree($lat), | |
"lng" => $this->minDectoDecDegree($lng) | |
); | |
} | |
public function minDectoDecDegree($coord){ | |
$coord = explode(" ",$coord); | |
return round((($coord[0]=="S"|$coord[0]=="W")?-1:1) * (floatval($coord[1]) + (floatval($coord[2])/60)),5); | |
} | |
public function getMutualCaches($user1,$user2){ | |
try { | |
$c1 = $this->getCachesFromUser($user1); | |
$c2 = $this->getCachesFromUser($user2); | |
} catch (Exception $e) { | |
throw $e; | |
} | |
return array_intersect($c1,$c2); | |
} | |
function checkUserExists($user){ | |
$url = "http://www.geocaching.com/seek/nearest.aspx?ul={$user}"; | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
$data = curl_exec($ch); | |
return $this->checkUserFound($data); | |
curl_close($ch); | |
} | |
function checkUserFound($data){ | |
//todo check that the page is a search result page | |
return !(preg_match('/<span id="ctl00_ContentBody_SearchResultText">Advanced Search<\/span>/i', $data)); | |
} | |
function getCachesFromUser($user){ | |
$url = "http://www.geocaching.com/seek/nearest.aspx?ul={$user}"; | |
$caches = array(); | |
$postData = array(); | |
// We'll correct this later. | |
$pages = 2; | |
for($page = 1; $page <= $pages; $page++){ | |
$data = $this->postGet($url,$postData); | |
// Check the user exists | |
if(!$this->checkUserFound($data)){ | |
throw new Exception('User "'.$user.'" does not exist.'); | |
} | |
// Correct the page count (if this is the first scrape) | |
if($page == 1){ | |
preg_match('/Page: <b>1<\/b> of <b>(.*?)<\/b>/i', $data, $regs); | |
$pages = $regs[1]; | |
} | |
// Extract the geocaches | |
preg_match_all('/\|\s*(GC[A-Z0-9]+)\s*\|/', $data, $arr); | |
$caches = array_merge($caches, $arr[1]); | |
// Need to advance list at multiples of 10 | |
if($page%10==0){ | |
$et = 'ctl00$ContentBody$pgrTop$ctl06'; | |
}else{ | |
$et = 'ctl00$ContentBody$pgrTop$lbGoToPage_'.($page+1); | |
} | |
// Prepare next postData | |
$postData = array( | |
"__EVENTTARGET" => $et, | |
"__EVENTARGUMENT" => (preg_match('/__EVENTARGUMENT\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
"__LASTFOCUS" => (preg_match('/__LASTFOCUS\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
"__VIEWSTATEFIELDCOUNT" => (preg_match('/__VIEWSTATEFIELDCOUNT\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
"__VIEWSTATE" => (preg_match('/__VIEWSTATE\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
"__VIEWSTATE1" => (preg_match('/__VIEWSTATE1\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
"__PREVIOUSPAGE" => (preg_match('/__PREVIOUSPAGE\" value=\"(.*)\"/i', $data, $regs))?$regs[1]:"", | |
'ctl00$tbUsername' => "", | |
'ctl00$tbPassword' => "", | |
'ctl00$ContentBody$chkHighlightBeginnerCaches' => "on" | |
); | |
} | |
return $caches; | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment