fix bug: route view should shownext trip to finish not next to start
fix bug: route view should shownext trip to finish not next to start

--- a/aws/awsStartup.sh
+++ b/aws/awsStartup.sh
@@ -5,6 +5,7 @@
 #http://www.how2forge.org/installing-lighttpd-with-php5-and-mysql-support-on-fedora-12
 
 cp /root/aws.php /tmp/
+mkdir /var/www/lib/staticmaplite/cache 
 chcon -h system_u:object_r:httpd_sys_content_t /var/www
 chcon -R -h root:object_r:httpd_sys_content_t /var/www/*
 chcon -R -t httpd_sys_content_rw_t /var/www/lib/staticmaplite/cache

--- a/feedback.php
+++ b/feedback.php
@@ -1,11 +1,11 @@
 <?php
-include ('include/common.inc.php');
+include ("include/common.inc.php");
 include_header("Feedback", "feedback");
 function sendEmail($topic, $message)
 {
 	$address = "maxious@lambdacomplex.org";
 	if (file_exists("/tmp/aws.php")) {
-		include_once ('lib/ses.php');
+		include_once ("lib/ses.php");
 		include_once ("/tmp/aws.php");
 		$con = new SimpleEmailService($accessKey, $secretKey);
 		//$con->verifyEmailAddress($address);
@@ -24,16 +24,29 @@
 		mail($address, $topic, $message);
 	}
 }
+
+$stopid = "";
+$stopcode = "";
+$urlparts = explode("?",$_SERVER["HTTP_REFERER"]);
+if (isset($urlparts[1])) {
+    $getparams = explode("&",$urlparts[1]);
+    foreach ($getparams as $param) {
+        $paramparts=explode("=",$param);
+        if ($paramparts[0] == "stopid") $stopid = $paramparts[1];
+        if ($paramparts[0] == "stopcode") $stopcode = $paramparts[1];
+    }
+}
+
 ?>
 <h3>Add/Move/Delete a Bus Stop Location</h3>
-StopID:
-or StopCode:
-<small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop <input type="text" name="stoplocation" /> </small>
+StopID: <input type="text" name="stopid" value="<?php echo $stopid ?>"/><br>
+or StopCode:  <input type="text" name="stopcode" value="<?php echo $stopcode ?>"/><br>
+<small> if you click on feedback from a stop page, these will get filled in automatically. else describe the location/street of the stop in one of these boxes </small><br>
 
-Suggested Stop Location (lat/long or words):
-<small> if your device supports javascript, you can pick a location from the map above</small>
+Suggested Stop Location (lat/long or words):  <input type="text" name="newlocation"/><br>
+<small> if your device supports javascript, you can pick a location from the map above</small><br>
 
-Submit!
+<input type="submit" value="Submit!"/>
 
 <h3>Bug Report/Feedback</h3>
 Please leave feedback about bugs/errors or general suggestions about improvements that could be made to the way the data is presented!
@@ -41,14 +54,17 @@
 </textarea>
 <textarea id="extrainfo">
 <?php
-  echo '  Referrer URL
-    User Agent
-    User host/IP
-    Server host/IP
-    Current date/time
-    Dump of $_SESSION ';
+  echo "Referrer URL: ".$_SERVER["HTTP_REFERER"];
+  echo "\nUser Agent: ".$_SERVER["HTTP_USER_AGENT"];
+  echo "\nUser host/IP: ".$_SERVER["HTTP_X_FORWARDED_FOR"]." ".$_SERVER["REMOTE_ADDR"]; 
+  echo "\nServer host/IP: ".php_uname("n");
+  echo "\nCurrent date/time: ". date("c");
+  echo "\nCurrent code revision: ".exec("git rev-parse --short HEAD");
+  echo "\nCurrent timetables version: ".@filemtime('cbrfeed.zip');
+  echo "\nDump of session: ".print_r($_SESSION,true);
 ?>
 </textarea>
 
-Submit!
+<input type="submit" value="Submit!"/>
 
+

--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -47,7 +47,7 @@
 	}
 	$output = "";
 	if ($collapsible) $output.= '<div data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
-	$output.= '<center><img src="' . curPageURL() . 'lib/staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&maptype=mapnik&markers=' . 
+	$output.= '<center><img src="' . curPageURL() . 'lib/staticmaplite/staticmap.php?center=' . $center . '&zoom=' . $zoom . '&size=' . $width . 'x' . $height . '&markers=' . 
 $markers . '" width=' . $width . ' height=' . $height . '></center>';
 	if ($collapsible) $output.= '</div>';
 	return $output;

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -36,9 +36,17 @@
 	if ($datepicker) echo '<link rel="stylesheet"  href="css/jquery.ui.datepicker.mobile.css" />';
 	if (isDebugServer()) echo '<link rel="stylesheet"  href="css/jquery-mobile-1.0a3.css" />
          <script type="text/javascript" src="js/jquery-1.5.js"></script>
+	 <script>$(document).bind("mobileinit", function(){
+  $.mobile.ajaxEnabled = false;
+});
+</script>
         <script type="text/javascript" src="js/jquery-mobile-1.0a3.js"></script>';
 	else echo '<link rel="stylesheet"  href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.css" />
         <script type="text/javascript" src="http://code.jquery.com/jquery-1.5.1.min.js"></script>
+	 <script>$(document).bind("mobileinit", function(){
+  $.mobile.ajaxEnabled = false;
+});
+</script>
         <script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.min.js"></script>';
 	if ($datepicker) echo '<script> 
 		//reset type=date inputs to text
@@ -81,6 +89,10 @@
     .min-width-480px .viaPoints {
         display: block;
     }
+    #extrainfo {
+    visibility: hidden;
+    display: none;
+    }
     // source http://webaim.org/techniques/skipnav/
     #skip a, #skip a:hover, #skip a:visited 
 { 
@@ -109,25 +121,32 @@
 		echo "<script>
 
 function success(position) {
+$('#error').val('Location now detected. Please wait for data to load.');
 $('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
-$.ajax({ url: \"common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
-$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;});
-$('#here').show();
+$.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
+location.reload(true);
 }
 function error(msg) {
- console.log(msg);
-}
-
+$('#error').val('Error: '+msg);
+}
+
+function geolocate() {
 if (navigator.geolocation) {
 var options = {
-      enableHighAccuracy: false,
+      enableHighAccuracy: true,
       timeout: 60000,
       maximumAge: 10000
 }
   navigator.geolocation.getCurrentPosition(success, error, options);
 }
-
-</script> ";
+}
+$(document).ready(function() {
+        $('#here').click(function(event) { $('#geolocate').val(geolocate()); return false;});
+$('#here').show();
+});
+";
+if (!isset($_SESSION['lat']) || $_SESSION['lat'] == "") echo "geolocate();";
+echo "</script> ";
 	}
 	if (isAnalyticsOn()) echo '
 <script type="text/javascript">'."
@@ -150,7 +169,8 @@
     document.title = "' . $pageTitle . '";
 });
 </script>
-	<div data-role="header"> 
+	<div data-role="header" data-position="inline">
+	<a href="'.$_SERVER["HTTP_REFERER"].'" data-icon="arrow-l" data-rel="back">Back</a> 
 		<h1>' . $pageTitle . '</h1>
 	</div><!-- /header -->
         <a name="maincontent" id="maincontent"></a>
@@ -159,12 +179,6 @@
 }
 function include_footer()
 {
-	if ($geolocate && isset($_SESSION['lat'])) {
-		echo "<script>
-        $('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;});
-$('#here').show();
-</script>";
-	}
 	echo '<div id="footer"><a href="about.php">About/Contact Us</a>&nbsp;<a href="feedback.php">Feedback/Bug Report</a></a>';
 	echo '</div>';
         if (isAnalyticsOn()) {
@@ -175,9 +189,9 @@
 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
     var s = document.getElementsByTagName('script')[0]; 
 s.parentNode.insertBefore(ga, s);
-  })();";
+  })();</script>";
          $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
-  echo '<img src="' . $googleAnalyticsImageUrl . '" />';
+  echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
     }
 }
 function timePlaceSettings($geolocate = false)
@@ -188,13 +202,13 @@
 		$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
 	}
 	if ($geoerror) {
-		echo '<div class="error">Sorry, but your location could not currently be detected.
+		echo '<div id="error">Sorry, but your location could not currently be detected.
         Please allow location permission, wait for your location to be detected,
         or enter an address/co-ordinates in the box below.</div>';
 	}
 	echo '<div data-role="collapsible" data-collapsed="' . !$geoerror . '">
         <h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3>
-        <form action="'.basename($_SERVER['PHP_SELF']).'" method="post">
+        <form action="'.basename($_SERVER['PHP_SELF'])."?".$_SERVER['QUERY_STRING'].'" method="post">
         <div class="ui-body"> 
 		<div data-role="fieldcontain">
 	            <label for="geolocate"> Current Location: </label>
@@ -202,7 +216,8 @@
 	        </div>
     		<div data-role="fieldcontain">
 		        <label for="time"> Time: </label>
-		    	<input type="time" name="time" id="time" value="' . (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")) . '"/> <a href="#" name="currentTime" id="currentTime">Current Time?</a>
+		    	<input type="time" name="time" id="time" value="' . (isset($_SESSION['time']) ? $_SESSION['time'] : date("H:i")) . '"/>
+			<a href="#" name="currentTime" id="currentTime" onClick="var d = new Date();'. "$('#time').val(d.getHours() +':'+ (d.getMinutes().toString().length = 1 ? '0'+ d.getMinutes():  d.getMinutes()));".'">Current Time?</a>
 	        </div>
 		<div data-role="fieldcontain">
 		    <label for="service_period"> Service Period:  </label>
@@ -220,7 +235,7 @@
 }
 function trackEvent($category, $action, $label = "", $value = -1) {
   if (isAnalyticsOn()) {
-    echo "<script> _gaq.push(['_trackEvent', $category, $action".($label != "" ? ", $label" : "").($value != -1 ? ", $value" : "")."]);";
+    echo "<script> _gaq.push(['_trackEvent', $category, $action".($label != "" ? ", $label" : "").($value != -1 ? ", $value" : "")."]);</script>";
   }
 }
 ?>

--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -5,8 +5,10 @@
 	"session",
 	"json",
 	"phperror",
-	"awsgtfs",
+	//"awsgtfs",
 	"awsotp",
+	//"squallotp",
+	//"vanilleotp",
 	"other"
 );
 if (isDebug("awsgtfs")) {
@@ -17,6 +19,12 @@
 $otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/';
 if (isDebug("awsotp") || php_uname('n') == "maxious.xen.prgmr.com") {
 	$otpAPIurl = 'http://bus-main.lambdacomplex.org:8080/opentripplanner-api-webapp/';
+}
+if (isDebug("squallotp")) {
+		$otpAPIurl = 'http://10.0.1.108:5080/opentripplanner-api-webapp/';
+}
+if (isDebug("vanilleotp")) {
+		$otpAPIurl = 'http://10.0.1.135:8080/opentripplanner-api-webapp/';
 }
 if (isDebug("phperror")) error_reporting(E_ALL ^ E_NOTICE);
 include_once ("common-geo.inc.php");
@@ -59,7 +67,7 @@
 			}
 		}
 	}
-	if ($_SESSION['lat'] != "" && isMetricsOn()) {
+	if ($_SESSION['lat'] != "" && isAnalyticsOn()) {
 		trackEvent("Geolocation","Updated Location", "Geocoded - ".($geocoded ? "Yes" : "No"));
 	}
 }

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -1,6 +1,6 @@
 <?php
 include ('include/common.inc.php');
-include_header("bus.lambdacomplex.org", "index", false, true)
+include_header("bus.lambdacomplex.org", "index", false)
 ?>
 <div data-role="page">
 	<div data-role="content">
@@ -12,7 +12,7 @@
             <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
                 <li data-role="list-divider">Timetables - Stops</li>
                 <li><a href="stopList.php">Major (Timing Point) Stops</a></li>
-		<li><a href="stopList.php">All Stops</a></li>
+		<li><a href="stopList.php?allstops=yes">All Stops</a></li>
 		<li><a href="stopList.php?suburbs=yes">Stops By Suburb</a></li>
 		<li><a class="nearby" href="stopList.php?nearby=yes">Nearby Stops</a></li>
             </ul>

--- /dev/null
+++ b/labs/OpenStreetMap.js
@@ -1,1 +1,165 @@
+/**
+ * Namespace: Util.OSM
+ */
+OpenLayers.Util.OSM = {};
 
+/**
+ * Constant: MISSING_TILE_URL
+ * {String} URL of image to display for missing tiles
+ */
+OpenLayers.Util.OSM.MISSING_TILE_URL = "/404.php";
+
+/**
+ * Property: originalOnImageLoadError
+ * {Function} Original onImageLoadError function.
+ */
+OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError;
+
+/**
+ * Function: onImageLoadError
+ */
+OpenLayers.Util.onImageLoadError = function() {
+    if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) {
+        this.src = OpenLayers.Util.OSM.MISSING_TILE_URL;
+    } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) {
+        // do nothing - this layer is transparent
+    } else {
+        OpenLayers.Util.OSM.originalOnImageLoadError;
+    }
+};
+
+/**
+ * Class: OpenLayers.Layer.OSM.Mapnik
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Mapnik
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tiles.bigtincan.com/${z}/${x}/${y}.png",
+            "http://b.tiles.bigtincan.com/${z}/${x}/${y}.png",
+            "http://c.tiles.bigtincan.com/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({ numZoomLevels: 19 }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik"
+});
+
+OpenLayers.Layer.OSM.NearMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Mapnik
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+	    "http://nearmap:findreality@web0.nearmap.com/maps/hl=en&nml=Vert&x=${x}&y=${y}&z=${z}",
+	    "http://nearmap:findreality@web1.nearmap.com/maps/hl=en&nml=Vert&x=${x}&y=${y}&z=${z}",
+	    "http://nearmap:findreality@web2.nearmap.com/maps/hl=en&nml=Vert&x=${x}&y=${y}&z=${z}",
+	    "http://nearmap:findreality@web3.nearmap.com/maps/hl=en&nml=Vert&x=${x}&y=${y}&z=${z}"
+        ];
+        options = OpenLayers.Util.extend({ numZoomLevels: 22 }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.NearMap"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.Osmarender
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Osmarender
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
+            "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png",
+            "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({ numZoomLevels: 18 }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.CycleMap
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.CycleMap
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://a.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png",
+            "http://b.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png",
+            "http://c.andy.sandbox.cloudmade.com/tiles/cycle/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({ numZoomLevels: 19 }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap"
+});
+
+/**
+ * Class: OpenLayers.Layer.OSM.Maplint
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.OSM>
+ */
+OpenLayers.Layer.OSM.Maplint = OpenLayers.Class(OpenLayers.Layer.OSM, {
+    /**
+     * Constructor: OpenLayers.Layer.OSM.Maplint
+     *
+     * Parameters:
+     * name - {String}
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, options) {
+        var url = [
+            "http://d.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png",
+            "http://e.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png",
+            "http://f.tah.openstreetmap.org/Tiles/maplint/${z}/${x}/${y}.png"
+        ];
+        options = OpenLayers.Util.extend({ numZoomLevels: 18, isBaseLayer: false, visibility: false }, options);
+        var newArguments = [name, url, options];
+        OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.OSM.Maplint"
+});
+

--- /dev/null
+++ b/labs/googlemaps.php
@@ -1,1 +1,29 @@
-
+<!DOCTYPE html>
+<html>
+<head>
+<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
+<style type="text/css">
+  html { height: 100% }
+  body { height: 100%; margin: 0px; padding: 0px }
+  #map_canvas { height: 100% }
+</style>
+<script type="text/javascript"
+    src="http://maps.google.com/maps/api/js?sensor=false">
+</script>
+<script type="text/javascript">
+  function initialize() {
+    var latlng = new google.maps.LatLng(-35.25, 149.125);
+    var myOptions = {
+      zoom: 10,
+      center: latlng,
+      mapTypeId: google.maps.MapTypeId.ROADMAP
+    };
+    var map = new google.maps.Map(document.getElementById("map_canvas"),
+        myOptions);
+  }
+</script>
+</head>
+<body onload="initialize()">
+  <div id="map_canvas" style="width:100%; height:100%"></div>
+</body>
+</html>

--- /dev/null
+++ b/labs/myway_api.json.php
@@ -1,1 +1,125 @@
+<?php
+function cleanString($subject)
+{
+	$subject = str_replace("&nbsp;", " ", $subject);
+	$subject = str_replace("&", "&amp;", $subject);
+	$subject = preg_replace('/[^\r\n\t\x20-\x7E\xA0-\xFF]/', '', $subject);
+	$subject = str_replace("  ", " ", $subject);
+	return trim($subject);
+}
+$return = Array();
+/*if (file_exists("mywayresponse.txt")) {
+	@$fh = fopen("mywayresponse.txt", 'r');
+	if ($fh) {
+		$pageHTML = fread($fh, filesize("mywayresponse.txt"));
+		fclose($fh);
+	}
+}*/
+//set POST variables
+$url = 'https://www.action.act.gov.au/ARTS/use_Funcs.asp';
+$field_mapping = Array(
+	"card_number" => "SRNO",
+	"DOBmonth" => "month",
+	"DOBday" => "day",
+	"DOByear" => "year",
+	"secret_answer" => "pwrd",
+	"button" => "button"
+);
+foreach (Array(
+	"card_number",
+	"DOBday",
+	"DOBmonth",
+	"DOByear"
+) as $field_name) {
+	if (isset($_REQUEST[$field_name])) {
+		$fields[$field_name] = filter_var($_REQUEST[$field_name], FILTER_SANITIZE_NUMBER_INT);
+	}
+	else {
+		$return["error"][] = $field_name. " parameter invalid or unspecified";
+	}
+}
+if (isset($_REQUEST['secret_answer'])) {
+	$fields['secret_answer'] = filter_var($_REQUEST['secret_answer'], FILTER_SANITIZE_STRING, Array(
+		FILTER_FLAG_NO_ENCODE_QUOTES,
+		FILTER_FLAG_STRIP_HIGH,
+		FILTER_FLAG_STRIP_LOW
+	));
+}
+else {
+	$return["error"][] = "secret_answer parameter invalid or unspecified";
+}
+$fields['button'] = 'Submit';
+$fields_string = "";
+//url-ify the data for the POST
+foreach ($fields as $key => $value) {
+	if (sizeof($value) === 0) $return['error'][] = $key . " parameter invalid or unspecified";
+	$fields_string.= $field_mapping[$key] . '=' . $value . '&';
+}
+$fields_string = rtrim($fields_string, '&');
+if (!isset($return['error'])) {
+	//open connection
+	$ch = curl_init();
+	//set the url, number of POST vars, POST data
+	curl_setopt($ch, CURLOPT_URL, $url);
+	curl_setopt($ch, CURLOPT_POST, count($fields));
+	curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
+	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+	curl_setopt($ch, CURLOPT_HEADER, 0);
+	curl_setopt($ch, CURLOPT_TIMEOUT, 30);
+	//execute post
+	$pageHTML = curl_exec($ch);
+	if (curl_errno($ch)) $return["error"][] = "Network error " . curl_errno($ch) . " " . curl_error($ch) . " " . $url . $fields_string;
+	//close connection
+	curl_close($ch);
+}
 
+if (!isset($return['error'])) {
+	include_once ('simple_html_dom.php');
+	$page = str_get_html($pageHTML);
+	$pageAlerts = $page->find(".smartCardAlert");
+	if (sizeof($pageAlerts) > 0) {
+		$return['error'][] = $pageAlerts[0]->plaintext;
+	}
+	if (!isset($return['error'])) {
+		$tableNum = 0;
+		$tableName = Array(
+			1 => "myway_carddetails",
+			2 => "myway_transactions"
+		);
+		foreach ($page->find("table") as $table) {
+			$tableNum++;
+			$tableColumns = Array();
+			$tableColumnNum = 0;
+			foreach ($table->find("th") as $th) {
+				$tableColumns[$tableColumnNum] = cleanString($th->plaintext);
+				$tableColumnNum++;
+			}
+			$tableRowNum = 0;
+			foreach ($table->find("tr") as $tr) {
+				$tableColumnNum = 0;
+				foreach ($tr->find("td") as $td) {
+					if ($tableNum == 1) $return[$tableName[$tableNum]][$tableColumns[$tableColumnNum]] = cleanString($td->plaintext);
+					else $return[$tableName[$tableNum]][$tableRowNum][$tableColumns[$tableColumnNum]] = cleanString($td->plaintext);
+					$tableColumnNum++;
+				}
+				$tableRowNum++;
+			}
+		}
+	}
+}
+if (sizeof($return) == 0) {
+$return['error'][] = "No data extracted from MyWay website - API may be out of date";
+}
+
+header('Content-Type: text/javascript; charset=utf8');
+// header('Access-Control-Allow-Origin: http://bus.lambdacomplex.org/');
+header('Access-Control-Max-Age: 3628800');
+header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE');
+if (isset($_GET['callback'])) {
+	$json = '(' . json_encode($return) . ');'; //must wrap in parens and end with semicolon
+	print_r($_GET['callback'] . $json); //callback is prepended for json-p
+	
+}
+else echo json_encode($return);
+?>
+

--- /dev/null
+++ b/labs/mywaybalance.php
@@ -1,1 +1,64 @@
+<?php
+include ('../include/common.inc.php');
+include_header("MyWay Balance", "mywayBalance", true, false, true);
+$return = Array();
+function printBalance($cardNumber, $date, $pwrd)
+{
+	global $return;
+	$return = json_decode(getPage(curPageURL() . "/myway_api.json.php?card_number=$cardNumber&DOBday={$date[0]}&DOBmonth={$date[1]}&DOByear={$date[2]}&secret_answer=$pwrd"), true);
+    
+        if (isset($return['error'])) {
+            echo "<font color=red>" . var_dump($return['error']) . "</font>";
+        } else {
+		echo "<h2>Balance: " . $return['myway_carddetails']['Card Balance'] . "</h2>";
+		echo '<ul data-role="listview" data-inset="true"><li data-role="list-divider"> Recent Transactions </li>';
+		foreach ($return['myway_transactions'] as $transaction) {
+			echo "<li><b>" . $transaction["Date / Time"] . "</b>";
+                        echo "<br><small>" . $transaction["TX Reference No / Type"]. "</small>";
+                        echo '<p class="ui-li-aside">'.$transaction["TX Amount"].'</p>';
+			echo "</li>";
+		}
+		echo "</ul>";
+	}
+}
+if (isset($_REQUEST['card_number']) && isset($_REQUEST['date']) && isset($_REQUEST['secret_answer'])) {
+	$cardNumber = $_REQUEST['card_number'];
+	$date = explode("/", $_REQUEST['date']);
+	$pwrd = $_REQUEST['secret_answer'];
+	if ($_REQUEST['remember'] == true) {
+		$_COOKIE['card_number'] = $cardNumber;
+		$_COOKIE['date'] = $date;
+		$_COOKIE['secret_answer'] = $pwrd;
+	}
+	printBalance($cardNumber, $date, $pwrd);
+}
+else if (isset($_COOKIE['card_number']) && isset($_COOKIE['date']) && isset($_COOKIE['secret_answer'])) {
+	$cardNumber = $_COOKIE['card_number'];
+	$date = explode("/", $_COOKIE['date']);
+	$pwrd = $_COOKIE['secret_answer'];
+	printBalance($cardNumber, $date, $pwrd);
+}
+else {
+	$date = (isset($_REQUEST['date']) ? filter_var($_REQUEST['date'], FILTER_SANITIZE_STRING) : date("m/d/Y"));
+	echo '<form action="" method="post">
+    <div data-role="fieldcontain">
+        <label for="card_number">Card number</label>
+        <input type="text" name="card_number" id="card_number" value="' . $card_number . '"  />
+    </div>
+    <div data-role="fieldcontain">
+        <label for="date"> Date of birth </label>
+        <input type="text" name="date" id="date" value="' . $date . '"  />
+    </div>
+        <div data-role="fieldcontain">
+        <label for="secret_answer"> Secret question answer </label>
+        <input type="text" name="secret_answer" id="secret_answer" value="' . $secret_answer . '"  />
+    </div>
+        <div data-role="fieldcontain">
+        <label for="remember"> Remember these details? </label>
+        <input type="checkbox" name="remember" id="remember"  checked="yes"  />
+    </div>
+        <input type="submit" value="Go!"></form>';
+}
+include_footer();
+?>
 

--- /dev/null
+++ b/labs/openlayers/OpenLayers.js
@@ -1,1 +1,2553 @@
+/*
 
+  OpenLayers.js -- OpenLayers Map Viewer Library
+
+  Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD
+  license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt
+  for the full text of the license.
+
+  Includes compressed code under the following licenses:
+
+  (For uncompressed versions of the code used please see the
+  OpenLayers SVN repository: <http://openlayers.org/>)
+
+*/
+
+/* Contains portions of Prototype.js:
+ *
+ * Prototype JavaScript framework, version 1.4.0
+ *  (c) 2005 Sam Stephenson <sam@conio.net>
+ *
+ *  Prototype is freely distributable under the terms of an MIT-style license.
+ *  For details, see the Prototype web site: http://prototype.conio.net/
+ *
+ *--------------------------------------------------------------------------*/
+
+/**  
+*  
+*  Contains portions of Rico <http://openrico.org/>
+* 
+*  Copyright 2005 Sabre Airline Solutions  
+*  
+*  Licensed under the Apache License, Version 2.0 (the "License"); you
+*  may not use this file except in compliance with the License. You
+*  may obtain a copy of the License at
+*  
+*         http://www.apache.org/licenses/LICENSE-2.0  
+*  
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+*  implied. See the License for the specific language governing
+*  permissions and limitations under the License. 
+*
+**/
+
+/**
+ * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
+ * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+/**
+ * Contains port