Merge branch 'master' of ssh://apples.lambdacomplex.org/git/bus
--- /dev/null
+++ b/betweenpoint.add.php
@@ -1,1 +1,50 @@
+<?php
+ /*
+ * GeoPo Encode in PHP
+ * @author : Shintaro Inagaki
+ * @param $location (Array)
+ * @return $geopo (String)
+ */
+ function geopoEncode($lat, $lng)
+ {
+ // 64characters (number + big and small letter + hyphen + underscore)
+ $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+
+ $geopo = "";
+ $scale = 7;
+
+ // Change a degree measure to a decimal number
+ $lat = ($lat + 90) / 180 * pow(8, 10);
+ $lng = ($lng + 180) / 360 * pow(8, 10);
+ // Compute a GeoPo code from head and concatenate
+ for ($i = 0; $i < $scale; $i++) {
+ $geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1);
+ }
+ return $geopo;
+ }
+
+ $conn = pg_connect("dbname=bus user=postgres password=snmc");
+ if (!$conn) {
+ echo "An error occured.\n";
+ exit;
+ }
+ if ($_REQUEST['newlatlng']) {
+ $latlng = explode(";", $_REQUEST['newlatlng']);
+ $lat = (float)$latlng[0];
+ $lng = (float)$latlng[1];
+
+ $geoPo = geopoEncode($lat, $lng);
+ $nodelat = (int)($lat * 10000000);
+ $nodelon = (int)($lng * 10000000);
+ echo($nodelat . "," . $nodelon . "=$geoPo<br>");
+ $sql = "INSERT INTO stops (geohash,lat,lng) VALUES ('$geoPo', '$nodelat', '$nodelon')";
+ $result = pg_query($conn, $sql);
+ if (!$result) {
+ echo("Error in SQL query: " . pg_last_error() . "<br>\n");
+ } else {
+ echo "Inserted new point at $geoPo <br>";
+ }
+ }
+ flush();
+?>
--- /dev/null
+++ b/betweenpoint.delete.php
@@ -1,1 +1,33 @@
-
+<?php
+
+ $conn = pg_connect("dbname=bus user=postgres password=snmc");
+ if (!$conn) {
+ echo "An error occured.\n";
+ exit;
+ }
+ if ($_REQUEST['oldgeopo']) {
+
+ $sql = " DELETE from stops WHERE geohash = '{$_REQUEST['oldgeopo']}'";
+ $result = pg_query($conn, $sql);
+ if (!$result) {
+ echo("Error in SQL query: " . pg_last_error() . "<br>\n");
+ } else {
+ echo "Deleted {$_REQUEST['oldgeopo']}<br>";
+ $updatedroutes = 0;
+ $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'");
+ while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) {
+ $newpoints = str_replace($_REQUEST['oldgeopo'].';', '', $outdatedroute['points']);
+ $sql = "UPDATE between_stops set points='$newpoints' where fromlocation = '{$outdatedroute['fromlocation']}' AND tolocation = '{$outdatedroute['tolocation']}' ";
+ $result = pg_query($conn, $sql);
+ if (!$result) {
+ echo("Error in SQL query: " . pg_last_error() . "<br>\n");
+ }
+ echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."<br>";
+
+ $updatedroutes++;
+ }
+ echo "updated $updatedroutes routes<br>";
+ }
+ }
+ flush();
+?>
--- /dev/null
+++ b/betweenpoint.move.php
@@ -1,1 +1,95 @@
-
+<?php
+ /*
+ * GeoPo Encode in PHP
+ * @author : Shintaro Inagaki
+ * @param $location (Array)
+ * @return $geopo (String)
+ */
+ function geopoEncode($lat, $lng)
+ {
+ // 64characters (number + big and small letter + hyphen + underscore)
+ $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+
+ $geopo = "";
+ $scale = 7;
+
+ // Change a degree measure to a decimal number
+ $lat = ($lat + 90) / 180 * pow(8, 10);
+ $lng = ($lng + 180) / 360 * pow(8, 10);
+ // Compute a GeoPo code from head and concatenate
+ for ($i = 0; $i < $scale; $i++) {
+ $geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1);
+ }
+ return $geopo;
+ }
+
+ /*
+ * GeoPo Decode in PHP
+ * @author : Shintaro Inagaki
+ * @param $geopo (String)
+ * @return $location (Array)
+ */
+ function geopoDecode($geopo)
+ {
+ // 64characters (number + big and small letter + hyphen + underscore)
+ $chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+ // Array for geolocation
+ $location = array();
+
+ for ($i = 0; $i < strlen($geopo); $i++) {
+ // What number of character that equal to a GeoPo code (0-63)
+ $order = strpos($chars, substr($geopo, $i, 1));
+ // Lat/Lng plus geolocation value of scale
+ $location['lat'] = $location['lat'] + floor($order % 8) * pow(8, 9 - $i);
+ $location['lng'] = $location['lng'] + floor($order / 8) * pow(8, 9 - $i);
+ }
+
+ // Change a decimal number to a degree measure, and plus revised value that shift center of area
+ $location['lat'] = $location['lat'] * 180 / pow(8, 10) + 180 / pow(8, strlen($geopo)) / 2 - 90;
+ $location['lng'] = $location['lng'] * 360 / pow(8, 10) + 360 / pow(8, strlen($geopo)) / 2 - 180;
+ $location['scale'] = strlen($geopo);
+
+ return $location;
+ }
+
+ $conn = pg_connect("dbname=bus user=postgres password=snmc");
+ if (!$conn) {
+ echo "An error occured.\n";
+ exit;
+ }
+ if ($_REQUEST['newlatlng']) {
+ $latlng = explode(";", $_REQUEST['newlatlng']);
+ $lat = (float)$latlng[0];
+ $lng = (float)$latlng[1];
+
+ $geoPo = geopoEncode($lat, $lng);
+ $nodelat = (int)($lat * 10000000);
+ $nodelon = (int)($lng * 10000000);
+ echo($nodelat . "," . $nodelon . "=$geoPo<br>");
+ $sql = "UPDATE stops SET geohash='$geoPo', lat='$nodelat', lng='$nodelon', name=null, suburb=null WHERE geohash = '{$_REQUEST['oldgeopo']}'";
+ $result = pg_query($conn, $sql);
+ if (!$result) {
+ echo("Error in SQL query: " . pg_last_error() . "<br>\n");
+ } else if (pg_affected_rows($result) == 0) {
+ echo ("Error 0 points moved, please refresh page and try again");
+ } else {
+ echo $_REQUEST['oldgeopo'] . " replaced with $geoPo <br>";
+ $updatedroutes = 0;
+ $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'");
+ while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) {
+ $newpoints = str_replace($_REQUEST['oldgeopo'], $geoPo, $outdatedroute['points']);
+ $sql = "UPDATE between_stops set points='$newpoints' where
+ fromlocation = '".pg_escape_string($outdatedroute['fromlocation']).
+ "' AND tolocation = '".pg_escape_string($outdatedroute['tolocation'])."' ";
+ $result = pg_query($conn, $sql);
+ if (!$result) {
+ echo("Error in SQL query: " . pg_last_error() . "<br>\n");
+ }
+ echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."<br>";
+ $updatedroutes++;
+ }
+ echo "updated $updatedroutes routes<br>";
+ }
+ }
+ flush();
+?>
--- a/betweenpoint.php
+++ b/betweenpoint.php
@@ -10,11 +10,46 @@
// create the ol map object
var map = new OpenLayers.Map('map');
- var osmtiles = new OpenLayers.Layer.OSM("local", "http://127.0.0.1/tiles/${z}/${x}/${y}.png")
+ var osmtiles = new OpenLayers.Layer.OSM("local", "/tiles/${z}/${x}/${y}.png")
// use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles
markers = new OpenLayers.Layer.Markers("Between Stop Markers");
-
+ //hanlde mousedown on regions that are not points by reporting latlng
+OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {
+ defaultHandlerOptions: {
+ 'single': true,
+ 'double': false,
+ 'pixelTolerance': 0,
+ 'stopSingle': false,
+ 'stopDouble': false
+ },
+
+ initialize: function(options) {
+ this.handlerOptions = OpenLayers.Util.extend(
+ {}, this.defaultHandlerOptions
+ );
+ OpenLayers.Control.prototype.initialize.apply(
+ this, arguments
+ );
+ this.handler = new OpenLayers.Handler.Click(
+ this, {
+ 'click': this.trigger
+ }, this.handlerOptions
+ );
+ },
+
+ trigger: function(e) {
+ var lonlat = map.getLonLatFromViewPortPx(e.xy).transform(
+ new OpenLayers.Projection("EPSG:900913"),
+ new OpenLayers.Projection("EPSG:4326")
+ );
+ $('form input[name="newlatlng"]').val(lonlat.lat + ";" + lonlat.lon );
+ }
+
+ });
+ var click = new OpenLayers.Control.Click();
+ map.addControl(click);
+ click.activate();
<?php
$conn = pg_connect("dbname=bus user=postgres password=snmc");
if (!$conn) {
@@ -34,12 +69,14 @@
marker.id="' . $stop['geohash'] . '";
markers.addMarker(marker);
marker.events.register("mousedown", marker, function() {
+
document.getElementById("between_points").innerHTML += this.id+";";
+$(\'form input[name="oldgeopo"]\').val(this.id);
});
';
}
?>
-var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32));
+var timeicon = new OpenLayers.Icon("icong.png",new OpenLayers.Size(16,16));
var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon });
map.addLayers([osmtiles, markers,timepoints]);
@@ -51,11 +88,31 @@
function submitBetween () {
$.post("betweenpoint.submit.php", $("#inputform").serialize(), function(html){
$("#response").html(html);
- //clearForms();
- return false;
- });
-};
-
+ clearForms();
+ return false;
+ });
+};
+function submitMove () {
+ $.post("betweenpoint.move.php", $("#moveform").serialize(), function(html){
+ $("#response").html(html);
+ clearForms();
+ return false;
+ });
+};
+function submitDelete () {
+ $.post("betweenpoint.delete.php", $("#moveform").serialize(), function(html){
+ $("#response").html(html);
+ clearForms();
+ return false;
+ });
+};
+function submitAdd () {
+ $.post("betweenpoint.add.php", $("#moveform").serialize(), function(html){
+ $("#response").html(html);
+ clearForms();
+ return false;
+ });
+};
function OnChange(dropdown)
{
var myindex = dropdown.selectedIndex
@@ -146,10 +203,11 @@
}
-
+ $processed = 0;
foreach ($paths as $path => $routes) {
if (!in_array($path, array_keys($completedPaths))) {
- echo "<option value=\"$routes:$path\">" . sizeof(explode(";", $routes)) . " $path</option>\n";
+ echo "<option value=\"$routes:$path\"> $path ($routes) </option>\n";
+ $processed++;
} else {
$completedRoutes = explode(";", $completedPaths[$path]);
$incompleteRoutes = "";
@@ -161,13 +219,14 @@
}
if ($incompleteRoutes != "") {
- echo "<option value=\"$incompleteRoutes:$path\">" . sizeof(explode(";", $incompleteRoutes)) . " $path</option>\n";
+ echo "<option value=\"$incompleteRoutes:$path\"> $path ($incompleteRoutes) </option>\n";
+ $processed++;
}
}
}
+ echo "</select>$processed";
?>
-</select>
from <input type="text" name="from" id="from"/>
to <input type="text" name="to" id="to"/>
<br>
@@ -178,6 +237,13 @@
<br>
<textarea name="between_points" id="between_points" rows="1" cols="120"></textarea>
</form>
+ <form id="moveform">
+oldgeopo <input type="text" name="oldgeopo" id="oldgeopo"/>
+newlatlng <input type="text" name="newlatlng" id="newlatlng" size="60"/>
+ <input type="button" onclick="javascript:submitMove()" value="Move!">
+ <input type="button" onclick="javascript:submitAdd()" value="Add!">
+ <input type="button" onclick="javascript:submitDelete()" value="Delete!">
+</form>
<div id="response">
<!-- Our message will be echoed out here -->
</div>
--- a/betweenpoint.submit.php
+++ b/betweenpoint.submit.php
@@ -5,9 +5,9 @@
exit;
}
print_r($_REQUEST);
-$reverse=$_REQUEST["reverse"];
-$from=$_REQUEST["from"];
-$to=$_REQUEST["to"];
+$reverse=(isset($_REQUEST["reverse"]) ? $_REQUEST["reverse"] : "off");
+$from=pg_escape_string($_REQUEST["from"]);
+$to=pg_escape_string($_REQUEST["to"]);
$routes=$_REQUEST["routes"] ;
$points=$_REQUEST["between_points"];
$sql = "INSERT INTO between_stops (fromLocation, toLocation, points, routes) VALUES('$from','$to','$points','$routes')";
--- a/busui/common.inc.php
+++ /dev/null
@@ -1,109 +1,1 @@
-<?php
-date_default_timezone_set('Australia/ACT');
-$APIurl = "http://localhost:8765";
-error_reporting(E_ALL ^ E_NOTICE);
-function isDebug()
-{
- return true;
-}
-
-function isFastDevice() {
- return true;
-}
-
-function include_header($pageTitle, $opendiv = true, $geolocate = false) {
- // if (isDebug()) // set php error level high
- echo '
-<!DOCTYPE html>
-<html>
- <head>
- <title>bus.lambdacomplex.org - '.$pageTitle.'</title>
- <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css" />
- <script src="http://code.jquery.com/jquery-1.4.3.min.js"></script><script type="text/javascript"
-src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script>
- <script type="text/javascript" src="docs/docs.js"></script>
- <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" />
- <link rel="apple-touch-icon" href="apple-touch-icon.png" />
-</head>
-<body>
- ';
-if ($opendiv) echo '<div data-role="page">
-
- <div data-role="header">
- <h1>'.$pageTitle.'</h1>
- <a href="index.php" data-icon="back" class="ui-btn-right">Home</a>
- </div><!-- /header -->
- <div data-role="content"> ';
-}
-
-function include_footer()
-{
- echo '</div>';
-}
-
-function service_period()
-{
-switch (date('w')){
-
-case 0:
- return 'sunday';
-case 6:
- return 'saturday';
-default:
- return 'weekday';
-}
-}
-
-function midnight_seconds()
-{
-// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html
- $secs = (date("G") * 3600) + (date("i") * 60) + date("s");
- return $secs;
-}
-
-function midnight_seconds_to_time($seconds)
-{
- $midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y"));
- return date("h:ia",$midnight+$seconds);
-}
-function getPage($url)
-{
- $ch = curl_init($url);
-curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
-curl_setopt( $ch, CURLOPT_HEADER, 0 );
-$page = curl_exec($ch);
-curl_close($ch);
-return $page;
-}
-function array_flatten($a,$f=array()){
- if(!$a||!is_array($a))return '';
- foreach($a as $k=>$v){
- if(is_array($v))$f=array_flatten($v,$f);
- else $f[$k]=$v;
- }
- return $f;
-}
-
-function staticmap($mapPoints)
-{
-$width = 300;
-$height = 300;
- if (sizeof($mapPoints) < 1) return "";
- if (sizeof($mapPoints) === 1) $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}";
- if (sizeof($mapPoints) > 1) $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; //TODO average points
- $markers = "";
- foreach ($mapPoints as $index => $mapPoint) {
- if (sizeof($mapPoints) === 1) {
- $markers .= $mapPoint[0].",".$mapPoint[1].",ol-marker";
- } else {
- $markers .= $mapPoint[0].",".$mapPoint[1].",lightblue".($index+1);
- }
- }
- return '<img src="staticmaplite/staticmap.php?center='.$center.'&zoom=14&size='.$width.'x'.$height.'&maptype=mapnik&markers='.$markers.'" width=$width height=$height>';
-}
-?>
-
-
--- a/busui/index.php
+++ /dev/null
@@ -1,32 +1,1 @@
-<?php
-include('common.inc.php');
-include_header("bus.lambdacomplex.org",false)
-?>
-<div data-role="page" data-theme="b" id="jqm-home" class="ui-page ui-body-b ui-page-active">
- <div id="jqm-homeheader">
- <center><h1 id="jqm-logo"><img src="apple-touch-icon.png" alt="jQuery Mobile Framework" width="64" height="64" />
- bus.lambdacomplex.org</h1></center>
- </div>
- <div data-role="content">
- <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
- <li data-role="list-divider">Stops</li>
- <li><a href="stopList.php">All stops List</a></li>
- <li class="nearby"><a href="stopList.php?nearby=yes">Nearby List</a></li>
- <li><a href="stopList.php?favourites=yes">Favourites List</a></li>
- </ul>
- <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
- <li data-role="list-divider">Routes</li>
- <li><a href="routeList.php">All Routes List</a></li>
- <li class="nearby"><a href="routeList.php?nearby=yes">Nearby List</a></li>
- <li><a href="routeList.php?favourites=yes">Favourites List</a></li>
- </ul>
- <div class="ui-body ui-body-c info">
- <p class="latlng"></p>
- Time: <?php echo date("H:m"); ?> <br>
- Service Period: <?php echo ucwords(service_period()); ?>
- </div>
- </div>
- </div>
- </body>
-</html>
--- a/busui/readme.txt
+++ /dev/null
@@ -1,30 +1,1 @@
-# input location (via GPS or favourites or search) and destination (via searchable list, optional)
-# http://10.0.1.153:8765/json/boundboxstops?n=-35.27568499917103&e=149.1346514225006&s=-35.279495003493516
-&w=149.12622928619385&limit=50
-# http://10.0.1.153:8765/json/stoptrips?stop=43&time=64440 # recursively call to show all services nearby, sort by distance, need to filter by service period
-# Hey, can pick destination again from a list filtered to places these stops go if you're curious!
-# http://10.0.1.153:8765/json/tripstoptimes?trip=2139 # Can recursively call and parse based on intended destination to show ETA
-# http://10.0.1.153:8765/json/triprows?trip=2139 # For pretty maps
-have to do
-/usr/sbin/setsebool -P httpd_can_network_connect=1
-on fedora
-
-might need http://forum.jquery.com/topic/google-maps-inside-jquery-mobile
-
-some extras
-/json/routes = all routes
-/json/neareststops?lat/lng/number
-TODO
-Destinations
-Favourites
-OOP stops/routes
-Stop sorting/search-filter
-
-static maps
-https://code.google.com/apis/maps/documentation/staticmaps/
-http://www.multimap.com/openapidocs/1.2/web_service/staticmaps.htm
-http://dev.openstreetmap.de/staticmap/ (os @ http://sourceforge.net/projects/staticmaplite/)
-(php and open source @ http://trac.openstreetmap.org/browser/sites/other/StaticMap?rev=16348)
-http://pafciu17.dev.openstreetmap.org/
-
--- a/busui/routeList.php
+++ /dev/null
@@ -1,55 +1,1 @@
-<?php
-include('common.inc.php');
-include_header("Routes");
-/* data-filter="true">';
-echo "<script> $('#routeList').listnav({prefixes: ['to'] }); </script>";*/
-echo ' <ul data-role="listview">';
-$url = $APIurl."/json/routes";
-$contents = json_decode(getPage($url));
-if ($_REQUEST['bynumber']) {
- $routeSeries = Array();
- foreach ($contents as $key => $row) {
- foreach (explode(" ",$row[1]) as $routeNumber ) {
- $seriesNum = substr($routeNumber, 0, -1)."0";
- if ($seriesNum == "0") $seriesNum = $routeNumber;
- $routeSeries[$seriesNum][$seriesNum."-".$row[1]."-".$row[0]] = $row;
-
-
- }
- }
- ksort($routeSeries);
- foreach ($routeSeries as $series => $routes)
- {
- echo '<li>'.$series."... <ul>\n";
- foreach($routes as $row) {
- echo '<li>'.$row[1].' <a href="route.php?routeid='.$row[0].'">'.$row[2]."</a></li>\n";
- }
- echo "</ul></li>\n";
- }
-} else {
- foreach ($contents as $key => $row) {
- $routeDestinations[$row[2]][] = $row;
- }
- foreach ($routeDestinations as $destination => $routes)
- {
- echo '<li>'.$destination."... <ul>\n";
- foreach($routes as $row) {
- echo '<li>'.$row[1].' <a href="trip.php?routeid='.$row[0].'">'.$row[2]."</a></li>\n";
- }
- echo "</ul></li>\n";
- }
-}
-echo "</ul>\n";
-echo'
- <div data-role="footer" data-id="foo1" data-position="fixed">
- <div data-role="navbar">
- <ul>
- <li><a href="routeList.php" class="ui-btn-active">By Final Destination...</a></li>
- <li><a href="routeList.php?bynumber=yes">By Number... </a></li>
- <li><a href="routeList.php?bysuburb=yes">By Suburb... </a></li>
- </ul>
- ';
-include_footer();
-?>
-
--- a/busui/schedule_viewer.py
+++ /dev/null
@@ -1,557 +1,1 @@
-#!/usr/bin/python2.5
-# Copyright (C) 2007 Google Inc.
-#
-# 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.
-
-"""
-An example application that uses the transitfeed module.
-
-You must provide a Google Maps API key.
-"""
-
-
-import BaseHTTPServer, sys, urlparse
-import bisect
-from gtfsscheduleviewer.marey_graph import MareyGraph
-import gtfsscheduleviewer
-import mimetypes
-import os.path
-import re
-import signal
-import simplejson
-import socket
-import time
-import transitfeed
-from transitfeed import util
-import urllib
-
-
-# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break
-# raise a KeyboardInterrupt.
-if hasattr(signal, 'SIGBREAK'):
- signal.signal(signal.SIGBREAK, signal.default_int_handler)
-
-
-mimetypes.add_type('text/plain', '.vbs')
-
-
-class ResultEncoder(simplejson.JSONEncoder):
- def default(self, obj):
- try:
- iterable = iter(obj)
- except TypeError:
- pass
- else:
- return list(iterable)
- return simplejson.JSONEncoder.default(self, obj)
-
-# Code taken from
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt
-# An alternate approach is shown at
-# http://mail.python.org/pipermail/python-list/2003-July/212751.html
-# but it requires multiple threads. A sqlite object can only be used from one
-# thread.
-class StoppableHTTPServer(BaseHTTPServer.HTTPServer):
- def server_bind(self):
- BaseHTTPServer.HTTPServer.server_bind(self)
- self.socket.settimeout(1)
- self._run = True
-
- def get_request(self):
- while self._run:
- try:
- sock, addr = self.socket.accept()
- sock.settimeout(None)
- return (sock, addr)
- except socket.timeout:
- pass
-
- def stop(self):
- self._run = False
-
- def serve(self):
- while self._run:
- self.handle_request()
-
-
-def StopToTuple(stop):
- """Return tuple as expected by javascript function addStopMarkerFromList"""
- return (stop.stop_id, stop.stop_name, float(stop.stop_lat),
- float(stop.stop_lon), stop.location_type)
-
-
-class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
- def do_GET(self):
- scheme, host, path, x, params, fragment = urlparse.urlparse(self.path)
- parsed_params = {}
- for k in params.split('&'):
- k = urllib.unquote(k)
- if '=' in k:
- k, v = k.split('=', 1)
- parsed_params[k] = unicode(v, 'utf8')
- else:
- parsed_params[k] = ''
-
- if path == '/':
- return self.handle_GET_home()
-
- m = re.match(r'/json/([a-z]{1,64})', path)
- if m:
- handler_name = 'handle_json_GET_%s' % m.group(1)
- handler = getattr(self, handler_name, None)
- if callable(handler):
- return self.handle_json_wrapper_GET(handler, parsed_params)
-
- # Restrict allowable file names to prevent relative path attacks etc
- m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path)
- if m and m.group(1):
- try:
- f, mime_type = self.OpenFile(m.group(1))
- return self.handle_static_file_GET(f, mime_type)
- except IOError, e:
- print "Error: unable to open %s" % m.group(1)
- # Ignore and treat as 404
-
- m = re.match(r'/([a-z]{1,64})', path)
- if m:
- handler_name = 'handle_GET_%s' % m.group(1)
- handler = getattr(self, handler_name, None)
- if callable(handler):
- return handler(parsed_params)
-
- return self.handle_GET_default(parsed_params, path)
-
- def OpenFile(self, filename):
- """Try to open filename in the static files directory of this server.
- Return a tuple (file object, string mime_type) or raise an exception."""
- (mime_type, encoding) = mimetypes.guess_type(filename)
- assert mime_type
- # A crude guess of when we should use binary mode. Without it non-unix
- # platforms may corrupt binary files.
- if mime_type.startswith('text/'):
- mode = 'r'
- else:
- mode = 'rb'
- return open(os.path.join(self.server.file_dir, filename), mode), mime_type
-
- def handle_GET_default(self, parsed_params, path):
- self.send_error(404)
-
- def handle_static_file_GET(self, fh, mime_type):
- content = fh.read()
- self.send_response(200)
- self.send_header('Content-Type', mime_type)
- self.send_header('Content-Length', str(len(content)))
- self.end_headers()
- self.wfile.write(content)
-
- def AllowEditMode(self):
- return False
-
- def handle_GET_home(self):
- schedule = self.server.schedule
- (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox()
- forbid_editing = ('true', 'false')[self.AllowEditMode()]
-
- agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8')
-
- key = self.server.key
- host = self.server.host
-
- # A very simple template system. For a fixed set of values replace [xxx]
- # with the value of local variable xxx
- f, _ = self.OpenFile('index.html')
- content = f.read()
- for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key',
- 'host', 'forbid_editing'):
- content = content.replace('[%s]' % v, str(locals()[v]))
-
- self.send_response(200)
- self.send_header('Content-Type', 'text/html')
- self.send_header('Content-Length', str(len(content)))
- self.end_headers()
- self.wfile.write(content)
-
- def handle_json_GET_routepatterns(self, params):
- """Given a route_id generate a list of patterns of the route. For each
- pattern include some basic information and a few sample trips."""
- schedule = self.server.schedule
- route = schedule.GetRoute(params.get('route', None))
- if not route:
- self.send_error(404)
- return
- time = int(params.get('time', 0))
- sample_size = 10 # For each pattern return the start time for this many trips
-
- pattern_id_trip_dict = route.GetPatternIdTri