Merge branch 'master' of https://github.com/maxious/ACTBus-ui
Merge branch 'master' of https://github.com/maxious/ACTBus-ui

Conflicts:
include/common.inc.php

file:b/.gitignore (new)
--- /dev/null
+++ b/.gitignore
@@ -1,1 +1,8 @@
 
+/labs/tiles/12
+/labs/tiles/13
+/labs/tiles/14
+/labs/tiles/15
+/labs/tiles/16
+/labs/tiles/17
+/labs/tiles/19

file:a/about.php -> file:b/about.php
--- a/about.php
+++ b/about.php
@@ -21,6 +21,10 @@
 , <a href="http://itunes.apple.com/au/app/act-buses/id376634797?mt=8">ACT Buses by David Sullivan</a>) 
 and Android (<a href="https://market.android.com/details?id=com.action">MyBus 2.0 by Imagine Team</a>)
 <br />
+GTFS-realtime API;
+Alerts and Trip Updates (but only Cancelled or Stop Skipped)
+Default format binary but can get JSON by adding ?ascii=yes
+<br />
 <br />
 <small>Disclaimer: The content of this website is of a general and informative nature. Please check with printed timetables or those available on http://action.act.gov.au before your trip.
 Whilst every effort has been made to ensure the high quality and accuracy of the Site, the Author makes no warranty, 

--- a/aws/busuiphp.sh
+++ b/aws/busuiphp.sh
@@ -2,9 +2,15 @@
 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
 chmod -R 777 /var/www/lib/staticmaplite/cache 
+
 chcon -R -t httpd_sys_content_rw_t /var/www/labs/tiles
 chmod -R 777 /var/www/labs/tiles
+
+chcon -R -t httpd_sys_content_rw_t /var/www/lib/openid-php/oid_store
+chmod -R 777 /var/www/lib/openid-php/oid_store
+
 wget http://s3-ap-southeast-1.amazonaws.com/busresources/cbrfeed.zip \
 -O /var/www/cbrfeed.zip

--- /dev/null
+++ b/include/common-auth.inc.php
@@ -1,1 +1,91 @@
+<?php
+function getScheme()
+{
+     $scheme = 'http';
+     if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
+        $scheme .= 's';
+         } 
+    return $scheme;
+    } 
 
+function getTrustRoot()
+{
+     return sprintf("%s://%s:%s%s/",
+         getScheme(), $_SERVER['SERVER_NAME'],
+         $_SERVER['SERVER_PORT'],
+         dirname($_SERVER['PHP_SELF']));
+    } 
+
+
+// Includes required files
+set_include_path(get_include_path() . PATH_SEPARATOR . $labsPath."lib/openid-php/");
+require_once "Auth/OpenID/Consumer.php";
+require_once "Auth/OpenID/FileStore.php";
+require_once "Auth/OpenID/AX.php";
+
+
+
+function login()
+{
+  // Just tested this with/for Google, needs trying with others ...
+$oid_identifier = 'https://www.google.com/accounts/o8/id';
+    // Create file storage area for OpenID data
+    $store = new Auth_OpenID_FileStore('lib/openid-php/oid_store');
+    // Create OpenID consumer
+    $consumer = new Auth_OpenID_Consumer($store);
+    // Create an authentication request to the OpenID provider
+    $auth = $consumer -> begin($oid_identifier);
+    
+    // Create attribute request object
+    // See http://code.google.com/apis/accounts/docs/OpenID.html#Parameters for parameters
+    // Usage: make($type_uri, $count=1, $required=false, $alias=null)
+    $attribute[] = Auth_OpenID_AX_AttrInfo :: make('http://axschema.org/contact/email', 2, 1, 'email');
+    $attribute[] = Auth_OpenID_AX_AttrInfo :: make('http://axschema.org/namePerson/first', 1, 1, 'firstname');
+    $attribute[] = Auth_OpenID_AX_AttrInfo :: make('http://axschema.org/namePerson/last', 1, 1, 'lastname');
+    
+    // Create AX fetch request
+    $ax = new Auth_OpenID_AX_FetchRequest;
+    
+    // Add attributes to AX fetch request
+    foreach($attribute as $attr) {
+        $ax -> add($attr);
+        } 
+    
+    // Add AX fetch request to authentication request
+    $auth -> addExtension($ax);
+    $_SESSION['returnURL'] = curPageURL();
+    // Redirect to OpenID provider for authentication
+    $url = $auth -> redirectURL(getTrustRoot(), $_SESSION['returnURL']);
+    header('Location: ' . $url);
+    } 
+
+
+function auth()
+
+{
+  if ($_SESSION['authed'] == true) return true;
+
+     // Create file storage area for OpenID data
+    $store = new Auth_OpenID_FileStore('lib/openid-php/oid_store');
+     // Create OpenID consumer
+    $consumer = new Auth_OpenID_Consumer($store);
+     // Create an authentication request to the OpenID provider
+    $response = $consumer -> complete($_SESSION['returnURL']);
+    
+     if ($response -> status == Auth_OpenID_SUCCESS) {
+        // Get registration informations
+        $ax = new Auth_OpenID_AX_FetchResponse();
+         $obj = $ax -> fromSuccessResponse($response);
+         $email = $obj -> data['http://axschema.org/contact/email'][0];
+         var_dump($email);
+         if ($email != "maxious@gmail.com") {
+            die("Access Denied");
+             } else {
+               $_SESSION['authed'] = true;
+             }
+        } else {
+        login();
+         } 
+    } 
+    if ($_REQUEST['janrain_nonce']) auth();
+?>

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -25,14 +25,14 @@
 }
 function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false)
 {
-	global $labsPath;
+	global $labsPath,$serviceAlertsEnabled;
 	echo '
 <!DOCTYPE html> 
 <html lang="en">
 	<head>
         <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1"> 	
-<title>' . $pageTitle . '</title>
+<title>' . $pageTitle . ' - Canberra Bus Timetable</title>
         <meta name="google-site-verification" content="-53T5Qn4TB_de1NyfR_ZZkEVdUNcNFSaYKSFkWKx-sY" />
 <link rel="dns-prefetch" href="//code.jquery.com">
 <link rel="dns-prefetch" href="//ajax.googleapis.com">
@@ -98,8 +98,11 @@
 function success(position) {
 $('#error').val('Location now detected. Please wait for data to load.');
 $('#geolocate').val(position.coords.latitude+','+position.coords.longitude);
-$.ajax({ url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
-location.reload(true);
+$.ajax({ async: false, 
+success: function(){
+	location.reload(true);
+  },
+url: \"include/common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+position.coords.longitude });
 }
 function error(msg) {
 $('#error').val('Error: '+msg);
@@ -156,11 +159,13 @@
 				echo '<div id="servicewarning">Buses are running on an altered timetable today due to industrial action/public holiday. See <a href="http://www.action.act.gov.au">http://www.action.act.gov.au</a> for details.</div>';
 			}
 		}
-		$serviceAlerts = getServiceAlerts("network","network");
-		foreach ($serviceAlerts['entities'] as $entity) {
-			echo "<div id='servicewarning'> From ".date("F j, g:i a",strtotime($entity['alert']['active_period']['start']))." to ". date("F j, g:i a", strtotime($entity['alert']['active_period']['end']))."<br>Warning: {$entity['alert']['description']['translation']} 
-			<br><a href='{$entity['alert']['url']['translation']}'>Source</a>  </div>";
+		if ($GTFSREnabled) {
+		$serviceAlerts = getServiceAlertsAsArray("agency","0");
+		foreach ($serviceAlerts['entity'] as $entity) {
+			echo "<div id='servicewarning'>".date("F j, g:i a",strtotime($entity['alert']['active_period'][0]['start']))." to ". date("F j, g:i a", strtotime($entity['alert']['active_period'][0]['end']))."{$entity['alert']['header_text']['translation'][0]['text']}<br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} 
+			<br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a>  </div>";
 		}
+	}
 	}
 }
 function include_footer()

--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -45,7 +45,48 @@
 		return "";
 	}
 }
-function getServiceAlerts($filter_class, $filter_id) {
+if ($GTFSREnabled) {
+$serviceAlertCause = Array(
+"UNKNOWN_CAUSE" => "Unknown cause",
+"OTHER_CAUSE" => "Other cause",
+"TECHNICAL_PROBLEM" => "Technical problem",
+"STRIKE" => "Strike",
+"DEMONSTRATION" => "Demonstration",
+"ACCIDENT" => "Accident",
+"HOLIDAY" => "Holiday",
+"WEATHER" => "Weather",
+"MAINTENANCE" => "Maintenance",
+"CONSTRUCTION" => "Construction",
+"POLICE_ACTIVITY" => "Police activity",
+"MEDICAL_EMERGENCY" => "Medical emergency"
+);
+$serviceAlertEffect = Array(
+"NO_SERVICE" => "No service",
+"REDUCED_SERVICE" => "Reduced service",
+"SIGNIFICANT_DELAYS" => "Significant delays",
+"DETOUR" => "Detour",
+"ADDITIONAL_SERVICE" => "Additional service",
+"MODIFIED_SERVICE" => "Modified service",
+"OTHER_EFFECT" => "Other effect",
+"UNKNOWN_EFFECT" => "Unknown effect",
+"STOP_MOVED" => "Stop moved");
+
+set_include_path(get_include_path() . PATH_SEPARATOR . $labsPath."lib/Protobuf-PHP/library/DrSlump/");
+
+include_once("Protobuf.php");
+include_once("Protobuf/Message.php");
+include_once("Protobuf/Registry.php");
+include_once("Protobuf/Descriptor.php");
+include_once("Protobuf/Field.php");
+
+include_once($labsPath."lib/Protobuf-PHP/gtfs-realtime.php");
+include_once("Protobuf/CodecInterface.php");
+include_once("Protobuf/Codec/PhpArray.php");
+include_once("Protobuf/Codec/Binary.php");
+include_once("Protobuf/Codec/Binary/Writer.php");
+include_once("Protobuf/Codec/Json.php");
+
+function getServiceAlerts($filter_class = "", $filter_id = "") {
 /*
 
   also need last modified epoch of client gtfs
@@ -54,40 +95,93 @@
             - stop
             - trip
             - network
-          - patterns (WHERE=)
+          - classes (WHERE=)
             - route (short_name or route_id)
             - street
             - stop
-            - trip */
-$return = Array();
-$return['header']['gtrtfs_version'] = "1";
-$return['header']['timestamp'] = time();
-$return['entities'] = Array();
+            - trip 
+            Currently support:
+            network inform
+            trip patch: stop remove
+            street inform: route inform, trip inform, stop inform
+            route patch: trip remove
+            */
+            $fm = new transit_realtime\FeedMessage();
+$fh = new transit_realtime\FeedHeader();
+$fh->setGtfsRealtimeVersion(1);
+$fh->setTimestamp(time());
+$fm->setHeader($fh);
 foreach(getCurrentAlerts() as $alert) {
-	$informedEntities = getInformedAlerts($alert['id'],$_REQUEST['filter_class'],$_REQUEST['filter_id']);
+$fe = new transit_realtime\FeedEntity();
+	$fe->setId($alert['id']);
+	$fe->setIsDeleted(false);
+	$alert = new transit_realtime\Alert();	
+		$tr = new transit_realtime\TimeRange();
+			$tr->setStart($alert['start']);
+			$tr->setEnd($alert['end']);
+		$alert-> addActivePeriod($tr);
+			$informedEntities = getInformedAlerts($alert['id'],$_REQUEST['filter_class'],$_REQUEST['filter_id']);
 	if (sizeof($informedEntities) >0) {
-		$entity = Array();
-		$entity['id'] = $alert['id'];
-		$entity['alert']['active_period']['start'] = $alert['start'];
-		$entity['alert']['active_period']['end'] = $alert['end'];
-		$entity['alert']['url']['translation'] = $alert['url'];
-		$entity['alert']['description']['translation'] = $alert['description'];
-		
-		foreach ($informedEntities as $informedEntity) {
-			$informed = Array();
-			$informed[$informedEntity['informed_class']."_id"] = $informedEntity['informed_id'];
-			if ($informedEntity['informed_action'] != "") $informed["x-action"] = $informedEntity['informed_action'];
-			$informed[$informedEntity['class']."_type"] = $informedEntity['type'];
-			$entity['informed'][] = $informed; 
-		}
-		$return['entities'][] = $entity;
-	}
-}
-return $return;
+		$informed = Array();
+		$es = new transit_realtime\EntitySelector();
+		if ($informedEntity['informed_class'] == "agency") {
+			$es->setAgencyId($informedEntity['informed_id']);
+		}
+		if ($informedEntity['informed_class'] == "stop") {
+			$es->setStopId($informedEntity['informed_id']);
+		}
+		if ($informedEntity['informed_class'] == "route") {
+			$es->setRouteId($informedEntity['informed_id']);
+		}
+		if ($informedEntity['informed_class'] == "trip") {
+			$td = new transit_realtime\TripDescriptor();
+				$td->setTripId($informedEntity['informed_id']);
+			$es->setTrip($td);
+		}
+		$alert-> addInformedEntity($es);
+	}
+		$alert->setCause(constant("transit_realtime\Alert\Cause::".$alert['cause']));
+		$alert->setEffect(constant("transit_realtime\Alert\Effect::".$alert['effect']));
+		$tsUrl = new transit_realtime\TranslatedString();
+			$tUrl = new transit_realtime\TranslatedString\Translation();
+				$tUrl->setText($alert['url']);
+				$tUrl->setLanguage("en");
+			$tsUrl->addTranslation($tUrl);
+		$alert->setUrl($tsUrl);
+		$tsHeaderText= new transit_realtime\TranslatedString();
+			$tHeaderText = new transit_realtime\TranslatedString\Translation();
+				$tHeaderText->setText($alert['header']);
+				$tHeaderText->setLanguage("en");
+			$tsHeaderText->addTranslation($tHeaderText);
+		$alert->setHeaderText($tsHeaderText);
+		$tsDescriptionText= new transit_realtime\TranslatedString();
+			$tDescriptionText = new transit_realtime\TranslatedString\Translation();
+				$tDescriptionText->setText($alert['description']);
+				$tDescriptionText->setLanguage("en");
+			$tsDescriptionText->addTranslation($tDescriptionText);
+		$alert->setDescriptionText($tsDescriptionText);
+	$fe->setAlert($alert);
+$fm->addEntity($fe);
+}
+return $fm;
+}
+function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\PhpArray();
+	return $codec->encode(getServiceAlerts($filter_class, $filter_id));
+}
+
+function getServiceAlertsAsBinary($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\Binary();
+	return $codec->encode(getServiceAlerts($filter_class, $filter_id));
+}
+
+function getServiceAlertsAsJSON($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\Json();
+	return $codec->encode(getServiceAlerts($filter_class, $filter_id));
 }
 function getServiceAlertsByClass() {
 	$return = Array();
-	$alerts = getServiceAlerts("","");
+	$alerts = getServiceAlertsAsArray("","");
 	foreach ($alerts['entities'] as $entity) {
 		foreach ($entity['informed'] as $informed) {
 			foreach($informed as $key => $value){
@@ -97,10 +191,70 @@
 					$id = $value;
 				}
 			}
-		$return[$class][$id]['entity'] = $entity;
-		$return[$class][$id]['action'] = $informed["x-action"];
-	}
-	}
+		$return[$class][$id][] = $entity;
+	}
+	}
+}
+
+function getTripUpdates($filter_class = "", $filter_id = "") {
+     $fm = new transit_realtime\FeedMessage();
+$fh = new transit_realtime\FeedHeader();
+$fh->setGtfsRealtimeVersion(1);
+$fh->setTimestamp(time());
+$fm->setHeader($fh);
+foreach(getCurrentAlerts() as $alert) {
+			$informedEntities = getInformedAlerts($alert['id'],$_REQUEST['filter_class'],$_REQUEST['filter_id']);
+	$stops = Array();
+		$routestrips = Array();
+		if (sizeof($informedEntities) >0) {
+		if ($informedEntity['informed_class'] == "stop" && $informed["x-action"] == "remove") {
+			$stops[] = $informedEntity['informed_id'];
+		}
+		if (($informedEntity['informed_class'] == "route" || $informedEntity['informed_class'] == "trip") && $informed["x-action"] == "patch" ) {
+			$routestrips[] = Array( "id" => $informedEntity['informed_id'],
+			"type"=>$informedEntity['informed_class']);
+		}
+		}
+foreach ($routestrips as $routetrip) {
+$fe = new transit_realtime\FeedEntity();
+	$fe->setId($alert['id'].$routetrip['id']);
+	$fe->setIsDeleted(false);
+	$tu = new transit_realtime\TripUpdate();	
+		$td = new transit_realtime\TripDescriptor();
+		if ($routetrip['type'] == "route") {
+			$td->setRouteId($routetrip['id']);
+			} else if ($routetrip['type'] == "trip") {
+				$td->setTripId($routetrip['id']);
+			}
+		$tu->setTrip($td);
+		foreach ($stops as $stop) {
+		$stu = new transit_realtime\TripUpdate\StopTimeUpdate();
+				$stu->setStopId($stop);
+				$stu->setScheduleRelationship(transit_realtime\TripUpdate\StopTimeUpdate\ScheduleRelationship::SKIPPED);
+		$tu->addStopTimeUpdate($stu);
+	}
+	$fe->setTripUpdate($tu);
+$fm->addEntity($fe);
+}		
+
+}
+return $fm;
+	
+}
+function getTripUpdatesAsArray($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\PhpArray();
+	return $codec->encode(getTripUpdates($filter_class, $filter_id));
+}
+
+function getTripUpdatesAsBinary($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\Binary();
+	return $codec->encode(getTripUpdates($filter_class, $filter_id));
+}
+
+function getTripUpdatesAsJSON($filter_class = "", $filter_id = "") {
+	$codec = new DrSlump\Protobuf\Codec\Json();
+	return $codec->encode(getTripUpdates($filter_class, $filter_id));
+}
 }
 ?>
 

--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -10,6 +10,7 @@
 	"database",
 	"other"
 );
+$GTFSREnabled = true;
 $cloudmadeAPIkey = "daa03470bb8740298d4b10e3f03d63e6";
 $googleMapsAPIkey = "ABQIAAAA95XYXN0cki3Yj_Sb71CFvBTPaLd08ONybQDjcH_VdYtHHLgZvRTw2INzI_m17_IoOUqH3RNNmlTk1Q";
 $otpAPIurl = 'http://localhost:8080/opentripplanner-api-webapp/';
@@ -31,8 +32,8 @@
 
 function isDebugServer()
 {
-	return php_sapi_name() == "cli" || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "10.0.1.154" || $_SERVER['SERVER_NAME'] == "10.1.0.4" || $_SERVER['SERVER_NAME'] == 
-"localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1") ;
+	return php_sapi_name() == "cli" || isset($_SERVER['SERVER_NAME']) && ( $_SERVER['SERVER_NAME'] == "azusa" || $_SERVER['SERVER_NAME'] == "vanille" 
+|| $_SERVER['SERVER_NAME'] == "localhost" || $_SERVER['SERVER_NAME'] == "127.0.0.1") ;
 }
 
 include_once ("common-geo.inc.php");
@@ -42,18 +43,22 @@
 
 include_once ("common-request.inc.php");
 include_once ("common-session.inc.php");
+include_once ("common-auth.inc.php");
 include_once ("common-template.inc.php");
 
 
 function isAnalyticsOn()
 {
-	return !isDebugServer();
+ $user_agent = $_SERVER['HTTP_USER_AGENT'];
+	return !isDebugServer() && !preg_match('/cloudkick/i', $user_agent) && !preg_match('/googlebot/i', $user_agent) && 
+!preg_match('/baidu/i', $user_agent);
 }
 function isDebug($debugReason = "other")
 {
 	global $debugOkay;
 	return in_array($debugReason, $debugOkay, false) && isDebugServer();
 }
+
 function debug($msg, $debugReason = "other")
 {
 	if (isDebug($debugReason)) echo "\n<!-- " . date(DATE_RFC822) . "\n $msg -->\n";
@@ -186,5 +191,6 @@
   } 
   return implode( $glue, $retVal ); 
 } 
+
 ?>
 

--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -1,211 +1,222 @@
 <?php
 function getRoute($routeID)
-{
-	global $conn;
-	$query = "Select * from routes where route_id = :routeID LIMIT 1";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->bindParam(":routeID", $routeID);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetch(PDO::FETCH_ASSOC);
-}
+
+{
+     global $conn;
+     $query = "Select * from routes where route_id = :routeID LIMIT 1";
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> bindParam(":routeID", $routeID);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetch(PDO :: FETCH_ASSOC);
+    } 
 
 function getRouteByFullName($routeFullName)
-{
-	global $conn;
-	$query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->bindParam(":routeFullName", $routeFullName);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetch(PDO::FETCH_ASSOC);
-}
+
+{
+     global $conn;
+     $query = "Select * from routes where route_short_name||route_long_name = :routeFullName LIMIT 1";
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> bindParam(":routeFullName", $routeFullName);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetch(PDO :: FETCH_ASSOC);
+    } 
 
 function getRoutes()
-{
-	global $conn;
-	$query = "Select * from routes order by route_short_name;";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetchAll();
-}
+
+{
+     global $conn;
+     $query = "Select * from routes order by route_short_name;";
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetchAll();
+    } 
 function getRoutesByNumber($routeNumber = "")
-{
-	global $conn;
-	if ($routeNumber != "") {
-		$query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes  join trips on trips.route_id =
+
+{
+     global $conn;
+     if ($routeNumber != "") {
+        $query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes  join trips on trips.route_id =
 routes.route_id join stop_times on stop_times.trip_id = trips.trip_id
 where route_short_name = :routeNumber OR route_short_name LIKE :routeNumber2 order by route_short_name;";
-	}
-	else {
-		$query = "SELECT DISTINCT route_short_name from routes order by route_short_name";
-	}
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	if ($routeNumber != "") {
-		$query->bindParam(":routeNumber", $routeNumber);
-                $routeNumber2 = "% ".$routeNumber;
-		$query->bindParam(":routeNumber2", $routeNumber2);
-	}
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetchAll();
-}
+         } 
+    else {
+        $query = "SELECT DISTINCT route_short_name from routes order by route_short_name";
+         } 
+    debug($query, "database");
+     $query = $conn -> prepare($query);
+     if ($routeNumber != "") {
+        $query -> bindParam(":routeNumber", $routeNumber);
+         $routeNumber2 = "% " . $routeNumber;
+         $query -> bindParam(":routeNumber2", $routeNumber2);
+         } 
+    $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetchAll();
+    } 
 function getRoutesByNumberSeries($routeNumberSeries = "")
-{
-	global $conn;
-	if (strlen($routeNumberSeries) == 1) {
-		return getRoutesByNumber($routeNumberSeries);
-	}
-	$seriesMin = substr($routeNumberSeries, 0, -1) . "0";
-	$seriesMax = substr($routeNumberSeries, 0, -1) . "9";
-	$query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes  join trips on trips.route_id =
+
+{
+     global $conn;
+     if (strlen($routeNumberSeries) == 1) {
+        return getRoutesByNumber($routeNumberSeries);
+         } 
+    $seriesMin = substr($routeNumberSeries, 0, -1) . "0";
+     $seriesMax = substr($routeNumberSeries, 0, -1) . "9";
+     $query = "Select distinct routes.route_id,routes.route_short_name,routes.route_long_name,service_id from routes  join trips on trips.route_id =
 routes.route_id join stop_times on stop_times.trip_id = trips.trip_id where to_number(route_short_name, 'FM999') between :seriesMin and :seriesMax OR route_short_name LIKE :routeNumberSeries order by route_short_name;";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->bindParam(":seriesMin", $seriesMin);
-	$query->bindParam(":seriesMax", $seriesMax);
-        $routeNumberSeries = "% ".substr($routeNumberSeries, 0, -1)."%";
-        $query->bindParam(":routeNumberSeries", $routeNumberSeries);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetchAll();
-}
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> bindParam(":seriesMin", $seriesMin);
+     $query -> bindParam(":seriesMax", $seriesMax);
+     $routeNumberSeries = "% " . substr($routeNumberSeries, 0, -1) . "%";
+     $query -> bindParam(":routeNumberSeries", $routeNumberSeries);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetchAll();
+    } 
 function getRouteNextTrip($routeID)
-{
-	global $conn;
-	$query = "select * from routes join trips on trips.route_id = routes.route_id
+
+{
+     global $conn;
+     $query = "select * from routes join trips on trips.route_id = routes.route_id
 join stop_times on stop_times.trip_id = trips.trip_id where
 arrival_time > :currentTime and routes.route_id = :routeID order by
 arrival_time limit 1";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->bindParam(":currentTime", current_time());
-	$query->bindParam(":routeID", $routeID);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	$r = $query->fetch(PDO::FETCH_ASSOC);
-
-	// past last trip of the day special case
-	if (sizeof($r) < 16) {
-		$query = "select * from routes join trips on trips.route_id = routes.route_id
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> bindParam(":currentTime", current_time());
+     $query -> bindParam(":routeID", $routeID);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    $r = $query -> fetch(PDO :: FETCH_ASSOC);
+    
+     // past last trip of the day special case
+    if (sizeof($r) < 16) {
+        $query = "select * from routes join trips on trips.route_id = routes.route_id
 join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID order by
 arrival_time DESC limit 1";
-		debug($query, "database");
-		$query = $conn->prepare($query);
-		$query->bindParam(":routeID", $routeID);
-		$query->execute();
-		if (!$query) {
-			databaseError($conn->errorInfo());
-			return Array();
-		}
-            
-		$r = $query->fetch(PDO::FETCH_ASSOC);
-	}
-	return $r;
-}
+         debug($query, "database");
+         $query = $conn -> prepare($query);
+         $query -> bindParam(":routeID", $routeID);
+         $query -> execute();
+         if (!$query) {
+            databaseError($conn -> errorInfo());
+             return Array();
+             } 
+        
+        $r = $query -> fetch(PDO :: FETCH_ASSOC);
+         } 
+    return $r;
+    } 
 function getTimeInterpolatedRouteAtStop($routeID, $stop_id)
-{
-	$nextTrip = getRouteNextTrip($routeID);
-	if ($nextTrip['trip_id']) {
-		foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) {
-			if ($tripStop['stop_id'] == $stop_id) return $tripStop;
-		}
-	}
-	return Array();
-}
+
+{
+     $nextTrip = getRouteNextTrip($routeID);
+     if ($nextTrip['trip_id']) {
+        foreach (getTimeInterpolatedTrip($nextTrip['trip_id']) as $tripStop) {
+            if ($tripStop['stop_id'] == $stop_id) return $tripStop;
+             } 
+        } 
+    return Array();
+    } 
 function getRouteTrips($routeID)
-{
-	global $conn;
-	$query = "select routes.route_id,trips.trip_id,service_id,arrival_time, stop_id, stop_sequence from routes join trips on trips.route_id = routes.route_id
+
+{
+     global $conn;
+     $query = "select routes.route_id,trips.trip_id,service_id,arrival_time, stop_id, stop_sequence from routes join trips on trips.route_id = routes.route_id
 join stop_times on stop_times.trip_id = trips.trip_id where routes.route_id = :routeID and stop_sequence = '1' order by
 arrival_time ";
-	debug($query, "database");
-	$query = $conn->prepare($query);
-	$query->bindParam(":routeID", $routeID);
-	$query->execute();
-	if (!$query) {
-		databaseError($conn->errorInfo());
-		return Array();
-	}
-	return $query->fetchAll();
-}
+     debug($query, "database");
+     $query = $conn -> prepare($query);
+     $query -> bindParam(":routeID", $routeID);
+     $query -> execute();
+     if (!$query) {
+        databaseError($conn -> errorInfo());
+         return Array();
+         } 
+    return $query -> fetchAll();
+    } 
 function getRoutesByDestination($destination = "", $service_period = "")
-{
-	global $conn;
-	if ($service_period == "") $service_period = service_period();
-	if ($destination != "") {
-		$query = "SELECT DISTINCT trips.route_id,route_short_name,route_long_name, service_id