Fix html validation errors on trip view
Fix html validation errors on trip view

--- a/css/local.css.php
+++ b/css/local.css.php
@@ -55,7 +55,7 @@
     visibility: hidden;
     display: none;
     }
-    #servicewarning {
+    .servicewarning {
     padding: 1em;
     margin-bottom: 0.5em;
     text-size: 0.2em;

--- a/include/common-geo.inc.php
+++ b/include/common-geo.inc.php
@@ -58,8 +58,8 @@
     $output = "";
     if ($collapsible)
         $output.= '<div class="map" data-role="collapsible" data-collapsed="true"><h3>Open Map...</h3>';
-   if (isIOSDevice()) $output.= '<img class="hiresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=2&amp;sensor=true" width=' . $width . ' height=' . $height . '>';
- else $output.= '<img class="lowresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=1&amp;format=jpg&amp;sensor=true" width=' . $width . ' height=' . $height . '>';
+   if (isIOSDevice()) $output.= '<img class="hiresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=2&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
+ else $output.= '<img class="lowresmap" src="http://maps.googleapis.com/maps/api/staticmap?size=' . $width . 'x' . $height . '&amp;' . $markers . '&amp;scale=1&amp;format=jpg&amp;sensor=true" width=' . $width . ' height=' . $height . ' alt="map of stop location">';
    
     if ($collapsible)
         $output.= '</div>';

--- a/include/common-request.inc.php
+++ b/include/common-request.inc.php
@@ -57,6 +57,12 @@
 if (isset($_REQUEST['stopids'])) {
     $stopids = explode(",", filter_var($_REQUEST['stopids'], FILTER_SANITIZE_STRING));
 }
+if (isset($_REQUEST['filterIncludeRoutes'])) {
+    $filterIncludeRoutes = explode(",", filter_var($_REQUEST['filterIncludeRoutes'], FILTER_SANITIZE_STRING));
+}
+if (isset($_REQUEST['filterHasStop'])) {
+    $filterHasStop = filter_var($_REQUEST['filterHasStop'], FILTER_SANITIZE_STRING);
+}
 if (isset($_REQUEST['tripid'])) {
     $tripid = filter_var($_REQUEST['tripid'], FILTER_SANITIZE_STRING);
 }

--- a/include/common-template.inc.php
+++ b/include/common-template.inc.php
@@ -42,7 +42,7 @@
 }
 
 function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false, $datepicker = false) {
-    global $basePath, $GTFSREnabled;
+    global $basePath, $GTFSREnabled, $stopid, $routeid;
     echo '
 <!DOCTYPE html> 
 <html lang="en">
@@ -59,14 +59,13 @@
         $jqmcss = $basePath . "css/jquery.mobile-$jqmVersion.css";
         $jqjs = $basePath . "js/jquery-1.6.4.min.js";
         $jqmjs = $basePath . "js/jquery.mobile-$jqmVersion.js";
-        
+
         $jqmcss = $basePath . "css/jquery.mobile-b90eab4935.css";
         $jqmjs = $basePath . "js/jquery.mobile-b90eab4935.js";
     } else {
         $jqmcss = "//code.jquery.com/mobile/$jqmVersion/jquery.mobile-$jqmVersion.min.css";
         $jqjs = "//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js";
         $jqmjs = "//code.jquery.com/mobile/$jqmVersion/jquery.mobile-$jqmVersion.min.js";
-
     }
     echo '<link rel="stylesheet"  href="' . $jqmcss . '" />
 	<script src="' . $jqjs . '"></script>
@@ -108,7 +107,7 @@
 }';
     echo '</style>';
     echo '<link rel="stylesheet"  href="' . $basePath . 'css/local.css.php" />';
-    if (isIOSDevice()){
+    if (isIOSDevice()) {
         echo '<meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  <link rel="apple-touch-startup-image" href="startup.png" />
@@ -174,19 +173,41 @@
         <a name="maincontent" id="maincontent"></a>
         <div data-role="content"> ';
         if ($GTFSREnabled) {
-        $overrides = getServiceOverride();
-        if (isset($overrides['service_id'])) {
-            if ($overrides['service_id'] == "noservice") {
-                echo '<div id="servicewarning">Buses are <strong>not running today</strong> due to industrial action/public holiday. See <a 
+            $overrides = getServiceOverride();
+            if (isset($overrides['service_id'])) {
+                if ($overrides['service_id'] == "noservice") {
+                    echo '<div class="servicewarning">Buses are <strong>not running today</strong> 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>';
-            } else {
-                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 = getServiceAlertsAsArray("agency", "0");
+                } else {
+                    echo '<div class="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 = Array();
+            $globalAlerts = getServiceAlertsAsArray("agency", "0");
+            if ($globalAlerts != null) {
+                // echo "getting alerts due to network wide";
+                $serviceAlerts = array_merge($serviceAlerts, $globalAlerts);
+            }
+            if (isset($stopid)) {
+                $stopAlerts = getServiceAlertsAsArray("stop", $stopid);
+                if ($stopAlerts != null) {
+                    // echo "getting alerts due to stop $stopid";
+                    $serviceAlerts = array_merge($serviceAlerts, $stopAlerts);
+                }
+            }
+            if (isset($routeid)) {
+                $routeAlerts = getServiceAlertsAsArray("route", $routeid);
+                if ($routeAlerts != null) {
+                    //    echo "getting alerts due to route $routeid";
+                    $serviceAlerts = array_merge($serviceAlerts, $routeAlerts);
+                }
+            }
             if (isset($serviceAlerts['entity']) && sizeof($serviceAlerts['entity']) > 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']} 
+                    echo "<div class='servicewarning'><b>{$entity['alert']['header_text']['translation'][0]['text']}</b>&nbsp;<small>"
+                    . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['start']) . " to "
+                    . date("F jS Y, g:i a", $entity['alert']['active_period'][0]['end']) . "</small>
+                            <br>Warning: {$entity['alert']['description_text']['translation'][0]['text']} 
                             <br><a href='{$entity['alert']['url']['translation'][0]['text']}'>Source</a>  </div>";
                 }
             }
@@ -208,13 +229,14 @@
 s.parentNode.insertBefore(ga, s);
   })();</script>";
         $googleAnalyticsImageUrl = googleAnalyticsGetImageUrl();
-        echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" /></noscript>';
+        echo '<noscript><img src="' . $googleAnalyticsImageUrl . '" alt=""/></noscript>';
     }
     echo "\n</div></div></body></html>";
 }
+
 function timeSettings() {
     global $service_periods;
-echo '<div id="settings" data-role="collapsible" data-collapsed="true">
+    echo '<div id="settings" data-role="collapsible" data-collapsed="true">
 <h3>Change Time (' . (isset($_REQUEST['time']) ? $_REQUEST['time'] : "Current Time,") . ' ' . ucwords(service_period()) . ')...</h3>
         <form action="' . basename($_SERVER['PHP_SELF']) . '" method="GET">
                <input type="hidden" name="suburb" id="suburb" value="' . (isset($_REQUEST['suburb']) ? $_REQUEST['suburb'] : "") . '"/>
@@ -230,10 +252,10 @@
 		<div data-role="fieldcontain">
 		    <label for="service_period"> Service Period:  </label>
 			<select name="service_period" id="service_period">';
-foreach ($service_periods as $service_period) {
-    echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>';
-}
-echo '</select>
+    foreach ($service_periods as $service_period) {
+        echo "<option value=\"$service_period\"" . (service_period() === $service_period ? " SELECTED" : "") . '>' . ucwords($service_period) . '</option>';
+    }
+    echo '</select>
 			<a href="#" style="display:none" name="currentPeriod" id="currentPeriod">Current Period?</a>
 		</div>
 		
@@ -241,8 +263,9 @@
                 </div></form>
             </div>';
 }
+
 function placeSettings() {
-    
+
     $geoerror = false;
     $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "";
 
@@ -275,14 +298,15 @@
 
 //stop list collapsing
 function stopCompare($stopName) {
-    return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)),0,9);
-}
-function stopGroupTitle($stopName,$stopdesc) {
-    if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /",$stopName)) {
-        $descParts =  explode("<br>",$stopdesc);
-         return trim(str_replace("Street: ","",$descParts[0]));
+    return substr(trim(preg_replace("/\(Platform.*/", "", $stopName)), 0, 9);
+}
+
+function stopGroupTitle($stopName, $stopdesc) {
+    if (preg_match("/Dr |Cct |Cir |Av |St |Cr |Parade |Way |Bank /", $stopName)) {
+        $descParts = explode("<br>", $stopdesc);
+        return trim(str_replace("Street: ", "", $descParts[0]));
     } else {
-        return trim(preg_replace("/\(Platform.*/", "",$stopName));
+        return trim(preg_replace("/\(Platform.*/", "", $stopName));
     }
 }
 

--- a/include/common-transit.inc.php
+++ b/include/common-transit.inc.php
@@ -149,69 +149,104 @@
           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) {
-            $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) {
-                $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);
+        $current_alerts = getCurrentAlerts();
+        $informed_count = 0;
+        if (sizeof($current_alerts) > 0) {
+
+            $fm = new transit_realtime\FeedMessage();
+            $fh = new transit_realtime\FeedHeader();
+            $fh->setGtfsRealtimeVersion(1);
+            $fh->setTimestamp(time());
+            $fm->setHeader($fh);
+            foreach ($current_alerts as $current_alert) {
+                $affectsFilteredEntities = false;
+                $fe = new transit_realtime\FeedEntity();
+                $fe->setId($current_alert['id']);
+                $fe->setIsDeleted(false);
+                $alert = new transit_realtime\Alert();
+                $tr = new transit_realtime\TimeRange();
+                $tr->setStart($current_alert['start']);
+                $tr->setEnd($current_alert['end']);
+                $alert->addActivePeriod($tr);
+                $informedEntities = getInformedAlerts($current_alert['id'], $filter_class, $filter_id);
+                if (sizeof($informedEntities) > 0) {
+
+                    $affectsFilteredEntities = true;
+                    foreach ($informedEntities as $informedEntity) {
+	$informed_count++;
+                    $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);
+}
+                }
+                if ($current_alert['cause'] != "") {
+                    $alert->setCause(constant("transit_realtime\Alert\Cause::" . $current_alert['cause']));
+                }
+                if ($current_alert['effect'] != "") {
+                    $alert->setEffect(constant("transit_realtime\Alert\Effect::" . $current_alert['effect']));
+                }
+                if ($current_alert['url'] != "") {
+                    $tsUrl = new transit_realtime\TranslatedString();
+                    $tUrl = new transit_realtime\TranslatedString\Translation();
+                    $tUrl->setText($current_alert['url']);
+                    $tUrl->setLanguage("en");
+                    $tsUrl->addTranslation($tUrl);
+                    $alert->setUrl($tsUrl);
+                }
+                if ($current_alert['header'] != "") {
+                    $tsHeaderText = new transit_realtime\TranslatedString();
+                    $tHeaderText = new transit_realtime\TranslatedString\Translation();
+                    $tHeaderText->setText($current_alert['header']);
+                    $tHeaderText->setLanguage("en");
+                    $tsHeaderText->addTranslation($tHeaderText);
+                    $alert->setHeaderText($tsHeaderText);
+                }
+                if ($current_alert['description'] != "") {
+                    $tsDescriptionText = new transit_realtime\TranslatedString();
+                    $tDescriptionText = new transit_realtime\TranslatedString\Translation();
+                    $tDescriptionText->setText(trim($current_alert['description']));
+                    $tDescriptionText->setLanguage("en");
+                    $tsDescriptionText->addTranslation($tDescriptionText);
+                    $alert->setDescriptionText($tsDescriptionText);
+                }
+                $fe->setAlert($alert);
+                if ($affectsFilteredEntities) {
+                    $fm->addEntity($fe);
+                }
+            }
+            if ($informed_count > 0) {
+                return $fm;
+            } else {
+                return null;
+            }
+        } else
+            return null;
+    }
+
+    function getServiceAlertsAsArray($filter_class = "", $filter_id = "") {
+
+        $alerts = getServiceAlerts($filter_class, $filter_id);
+        if ($alerts != null) {
+            $codec = new DrSlump\Protobuf\Codec\PhpArray();
+
+            return $codec->encode($alerts);
+        } else {
+            return null;
         }
-        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 = "") {

--- a/include/common.inc.php
+++ b/include/common.inc.php
@@ -51,8 +51,9 @@
         || strstr($_SERVER['PHP_SELF'], "lib/")
         || strstr($_SERVER['PHP_SELF'], "geo/")
         || strstr($_SERVER['PHP_SELF'], "include/")
-        || strstr($_SERVER['PHP_SELF'], "servicealerts/"))
+        || strstr($_SERVER['PHP_SELF'], "rtpis/")) {
     $basePath = "../";
+}
 
 function isDebugServer() {
     

--- a/include/db/route-dao.inc.php
+++ b/include/db/route-dao.inc.php
@@ -59,7 +59,12 @@
         databaseError($conn->errorInfo());
         return Array();
     }
-    return $query->fetchAll();
+    $results = $query->fetchAll();
+    if (is_array($results)) {
+        return $results;
+    } else {
+        return Array($results);
+    }
 }
 function getRouteDescription($routeID, $directionID) {
     $trip = getRouteNextTrip($routeID, $directionID);
@@ -97,7 +102,7 @@
 function getRoutesByNumberSeries($routeNumberSeries = "") {
     global $conn;
     if (strlen($routeNumberSeries) == 1) {
-        return getRoutesByNumber($routeNumberSeries);
+        return getRoute($routeNumberSeries);
     }
     $seriesMin = substr($routeNumberSeries, 0, -1) . "0";
     $seriesMax = substr($routeNumberSeries, 0, -1) . "9";
@@ -120,7 +125,7 @@
 function getRouteNextTrip($routeID, $directionID) {
     global $conn;
    
-    $query = "select routes.route_id,direction_id,trips.trip_id,trip_headsign,departure_time from routes join trips on trips.route_id = routes.route_id
+    $query = "select routes.route_id,routes.route_url,direction_id,trips.trip_id,trip_headsign,departure_time,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  arrival_time between :currentTime and :futureTime 
 and routes.route_id = :routeID and trips.direction_id = :directionID order by
 arrival_time limit 1";

--- a/include/db/servicealert-dao.inc.php
+++ b/include/db/servicealert-dao.inc.php
@@ -44,17 +44,19 @@
     return $query->fetch(PDO :: FETCH_ASSOC);
 }
 
-function updateServiceAlert($alertID, $start, $end, $header, $description, $url) {
+function updateServiceAlert($alertID, $alert) {
     global $conn;
-    $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url where id = :servicealert_id';
+    $query = 'update servicealerts_alerts set start=:start, "end"=:end, header=:header, description=:description, url=:url, cause=:cause, effect=:effect where id = :servicealert_id';
     debug($query, "database");
     $query = $conn->prepare($query);
-    $query->bindParam(":servicealert_id", $alertID);
-    $query->bindParam(":start", $start);
-    $query->bindParam(":end", $end);
-    $query->bindParam(":header", $header);
-    $query->bindParam(":description", $description);
-    $query->bindParam(":url", $url);
+    $query->bindValue(":servicealert_id", $alertID);
+    $query->bindValue(":start", $alert['startdate']);
+    $query->bindValue(":end", $alert['enddate']);
+    $query->bindValue(":header", $alert['header']);
+    $query->bindValue(":description", $alert['description']);
+    $query->bindValue(":url", $alert['url']);
+    $query->bindValue(":cause", $alert['cause']);
+    $query->bindValue(":effect", $alert['effect']);
     $query->execute();
 
     print_r($conn->errorInfo());
@@ -65,16 +67,19 @@
     return $query->fetch(PDO :: FETCH_ASSOC);
 }
 
-function addServiceAlert($start, $end, $header, $description, $url) {
+function addServiceAlert($alert) {
     global $conn;
-    $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url) VALUES (:start, :end, :header, :description, :url) ';
+    $query = 'INSERT INTO servicealerts_alerts (start, "end", header, description, url,cause,effect) VALUES (:start, :end, :header, :description, :url,:cause,:effect) ';
     debug($query, "database");
     $query = $conn->prepare($query);
-    $query->bindParam(":start", $start);
-    $query->bindParam(":end", $end);
-    $query->bindParam(":header", $header);
-    $query->bindParam(":description", $description);
-    $query->bindParam(":url", $url);
+    //print_r($alert);
+    $query->bindValue(":start", $alert['startdate']);
+    $query->bindValue(":end", $alert['enddate']);
+    $query->bindValue(":header", $alert['header']);
+    $query->bindValue(":description", $alert['description']);
+    $query->bindValue(":url", $alert['url']);
+    $query->bindValue(":cause", $alert['cause']);
+    $query->bindValue(":effect", $alert['effect']);
     $query->execute();
 
     print_r($conn->errorInfo());
@@ -114,6 +119,7 @@
 function getInformedAlerts($id, $filter_class, $filter_id) {
 
     global $conn;
+    //echo "$id, $filter_class, $filter_id\n";
     $query = "SELECT * from servicealerts_informed where servicealert_id = :servicealert_id";
 
     if ($filter_class != "") {
@@ -158,12 +164,14 @@
 
 function addInformedAlert($serviceAlertID, $class, $id, $action) {
     global $conn;
-    $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id) VALUES(:servicealert_id ,:informed_class, :informed_id)';
+    $query = 'INSERT INTO servicealerts_informed (servicealert_id , informed_class , informed_id, informed_action) 
+        VALUES(:servicealert_id ,:informed_class, :informed_id, :informed_action)';
     debug($query, "database");
     $query = $conn->prepare($query);
     $query->bindParam(":servicealert_id", $serviceAlertID);
     $query->bindParam(":informed_class", $class);
     $query->bindParam(":informed_id", $id);
+    $query->bindParam(":informed_action", $action);
     $query->execute();
 
     print_r($conn->errorInfo());

--- a/include/db/stop-dao.inc.php
+++ b/include/db/stop-dao.inc.php
@@ -89,7 +89,7 @@
     $query = "Select * from stops where stop_name LIKE :name;";
     debug($query, "database");
     $query = $conn->prepare($query);
-    $name = "%" . $name . ";%";
+    $name = $name . "%";
     $query->bindParam(":name", $name);
     $query->execute();
     if (!$query) {

--- a/include/db/trip-dao.inc.php
+++ b/include/db/trip-dao.inc.php
@@ -51,6 +51,25 @@
     }
     return $query->fetchAll();
 }
+
+function getTripHasStop($tripID, $stopID) {
+        global $conn;
+    $query = "SELECT stop_id
+FROM stop_times
+join trips on trips.trip_id = stop_times.trip_id
+WHERE trips.trip_id = :tripID and stop_times.stop_id = :stopID";
+    debug($query, "database");
+    $query = $conn->prepare($query);
+    $query->bindParam(":tripID", $tripID);
+    $query->bindParam(":stopID", $stopID);
+    $query->execute();
+    if (!$query) {
+        databaseError($conn->errorInfo());
+        return Array();
+    }
+    return ($query->fetchColumn() > 0);
+}
+
 function getTripShape($tripID) {
     // todo, use shapes table if shape_id specified
     global $conn;

--- a/routeList.php
+++ b/routeList.php
@@ -50,17 +50,17 @@
     echo '  <ul data-role="listview" data-filter="true" data-inset="true" >';
     foreach ($routes as $route) {
         $time = getRouteAtStop($route['route_id'], $route['direction_id'], $route['stop_id']);
- $start = getTripStartingPoint($time['trip_id']); 
-    $end = getTripDestination($time['trip_id']);
+        $start = getTripStartingPoint($time['trip_id']);
+        $end = getTripDestination($time['trip_id']);
         //print_r($route);
         echo '<li> <a href="trip.php?routeid=' . $route['route_id'] . '&directionid=' . $route['direction_id'] . '"><h3>' . $route['route_short_name'] . "</h3>
                    
-                <p>" . $time['trip_headsign'] . (strstr($time['trip_headsign'], "bound") === false ? "bound" : "") . " from ".$start['stop_name']." to ".$end['stop_name'] . " (" . ucwords($time['service_id']) . ")</p>";
+                <p>" . $time['trip_headsign'] . (strstr($time['trip_headsign'], "bound") === false ? "bound" : "") . " from " . $start['stop_name'] . " to " . $end['stop_name'] . " (" . ucwords($time['service_id']) . ")</p>";
         $stop = getStop($route['stop_id']);
-echo "<p>Board at ".$stop['stop_name']."</p>";
+        echo "<p>Board at " . $stop['stop_name'] . "</p>";
         echo '<span class="ui-li-count">' . ($time['arrival_time'] ? $time['arrival_time'] : "No more trips today") . "<br>" . floor($route['distance']) . 'm away</span>';
-        
-    echo"       </a></li>\n";
+
+        echo"       </a></li>\n";
     }
 }
 
@@ -92,7 +92,8 @@
 } else if (isset($nearby)) {
     $routes = Array();
     include_header("Routes Nearby", "routeList", true, true);
-    if (isset($_SESSION['lat'])) trackEvent("Route Lists", "Routes Nearby", $_SESSION['lat'] . "," . $_SESSION['lon']);
+    if (isset($_SESSION['lat']))
+        trackEvent("Route Lists", "Routes Nearby", $_SESSION['lat'] . "," . $_SESSION['lon']);
     navbar();
     placeSettings();
     if (!isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == "") {
@@ -132,7 +133,7 @@
                     $seriesRange[$seriesNum]['max'] = $routeNumber;
                     $seriesRange[$seriesNum]['min'] = $routeNumber;
                 }
-                $routeSeries[$seriesNum][$seriesNum . "-" . $row[1] . "-" . $row[0]] = $row;
+                $routeSeries[$seriesNum][] = null;
             }
         }
         ksort($routeSeries);
@@ -157,7 +158,8 @@
         displayRoutes(getRoutesByDestination($routeDestination));
     } else {
         foreach (getRoutesByDestination() as $destination) {
-            echo '<li><a href="' . curPageURL() . '/routeList.php?routeDestination=' . urlencode($destination['stop_name']) . '">' . $destination['stop_name'] . "... </a></li>\n";
+            echo '<li><a href="' . curPageURL() . '/routeList.php?routeDestination='
+            . urlencode($destination['stop_name']) . '">' . $destination['stop_name'] . "... </a></li>\n";
         }
     }
 }

--- /dev/null
+++ b/rtpis/gtfs-realtime.php
@@ -1,1 +1,85 @@
+<?php
 
+/*
+ *    Copyright 2010,2011 Alexander Sadleir 
+
+  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.
+ */
+include ('../include/common.inc.php');
+function accept_header($header = false) {
+    // http://jrgns.net/parse_http_accept_header
+    $toret = null;
+    $header = $header ? $header : (array_key_exists('HTTP_ACCEPT', $_SERVER) ? $_SERVER['HTTP_ACCEPT']: false);
+    if ($header) {
+        $types = explode(',', $header);
+        $types = array_map('trim', $types);
+        foreach ($types as $one_type) {
+            $one_type = explode(';', $one_type);
+            $type = array_shift($one_type);
+            if ($type) {
+                list($precedence, $tokens) = self::accept_header_options($one_type);
+                list($main_type, $sub_type) = array_map('trim', explode('/', $type));
+                $toret[] = array('main_type' => $main_type, 'sub_type' => $sub_type, 'precedence' => (float)$precedence, 'tokens' => $tokens);
+            }
+        }
+        usort($toret, array('Parser', 'compare_media_ranges'));
+    }
+    return $toret;
+}
+function usage() {
+echo "Usage notes: Must specify format json/protobuf and gtfs-realtime feedtype alerts/updates. If callback is specified, will provide jsonp. Can filter with parmaters filter_class route/stop and filter_id with the id specified in GTFS.";