<?php | <?php |
function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false) | function include_header($pageTitle, $pageType, $opendiv = true, $geolocate = false) |
{ | { |
echo ' | echo ' |
<!DOCTYPE html> | <!DOCTYPE html> |
<html> | <html> |
<head> | <head> |
<title>' . $pageTitle . '</title>'; | <title>' . $pageTitle . '</title>'; |
if (isDebugServer()) echo '<link rel="stylesheet" href="css/jquery-mobile-1.0a3.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 type="text/javascript" src="js/jquery-1.5.js"></script> |
<script type="text/javascript" src="js/jquery-mobile-1.0a3.js"></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.css" /> | else echo '<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.css" /> |
<script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script> | <script type="text/javascript" src="http://code.jquery.com/jquery-1.5.js"></script> |
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.js"></script>'; | <script type="text/javascript" src="http://code.jquery.com/mobile/1.0a3/jquery.mobile-1.0a3.js"></script>'; |
echo ' | echo ' |
<link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" /> | <link rel="stylesheet" href="css/jquery.ui.datepicker.mobile.css" /> |
<script> | <script> |
//reset type=date inputs to text | //reset type=date inputs to text |
$( document ).bind( "mobileinit", function(){ | $( document ).bind( "mobileinit", function(){ |
$.mobile.page.prototype.options.degradeInputs.date = true; | $.mobile.page.prototype.options.degradeInputs.date = true; |
}); | }); |
</script> | </script> |
<script src="js/jQuery.ui.datepicker.js"></script> | <script src="js/jQuery.ui.datepicker.js"></script> |
<script src="js/jquery.ui.datepicker.mobile.js"></script> | <script src="js/jquery.ui.datepicker.mobile.js"></script> |
<style type="text/css"> | <style type="text/css"> |
.ui-navbar { | .ui-navbar { |
width: 100%; | width: 100%; |
} | } |
.ui-btn-inner { | .ui-btn-inner { |
white-space: normal !important; | white-space: normal !important; |
} | } |
.ui-li-heading { | .ui-li-heading { |
white-space: normal !important; | white-space: normal !important; |
} | } |
.ui-listview-filter { | .ui-listview-filter { |
margin: 0 !important; | margin: 0 !important; |
} | } |
.ui-icon-navigation { | .ui-icon-navigation { |
background-image: url(css/images/113-navigation.png); | background-image: url(css/images/113-navigation.png); |
background-position: 1px 0; | background-position: 1px 0; |
} | } |
#footer { | #footer { |
text-size: 0.75em; | text-size: 0.75em; |
text-align: center; | text-align: center; |
} | } |
body { | body { |
background-color: #F0F0F0; | background-color: #F0F0F0; |
} | } |
</style> | </style> |
<meta name="apple-mobile-web-app-capable" content="yes" /> | <meta name="apple-mobile-web-app-capable" content="yes" /> |
<meta name="apple-mobile-web-app-status-bar-style" content="black" /> | <meta name="apple-mobile-web-app-status-bar-style" content="black" /> |
<link rel="apple-touch-startup-image" href="startup.png" /> | <link rel="apple-touch-startup-image" href="startup.png" /> |
<link rel="apple-touch-icon" href="apple-touch-icon.png" />'; | <link rel="apple-touch-icon" href="apple-touch-icon.png" />'; |
if ($geolocate) { | if ($geolocate) { |
echo "<script> | echo "<script> |
function success(position) { | function success(position) { |
$('#geolocate').val(position.coords.latitude+','+position.coords.longitude); | $('#geolocate').val(position.coords.latitude+','+position.coords.longitude); |
$.ajax({ url: \"common.inc.php?geolocate=yes&lat=\"+position.coords.latitude+\"&lon=\"+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').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); |
$('#here').show(); | $('#here').show(); |
} | } |
function error(msg) { | function error(msg) { |
console.log(msg); | console.log(msg); |
} | } |
if (navigator.geolocation) { | if (navigator.geolocation) { |
navigator.geolocation.getCurrentPosition(success, error); | navigator.geolocation.getCurrentPosition(success, error); |
} | } |
</script> "; | </script> "; |
} | } |
echo '</head> | echo '</head> |
<body> | <body> |
'; | '; |
if (isMetricsOn()) { | if (isMetricsOn()) { |
require_once ('owa/owa_env.php'); | require_once ('owa/owa_env.php'); |
require_once (OWA_DIR . 'owa_php.php'); | require_once (OWA_DIR . 'owa_php.php'); |
$owa = new owa_php(); | $owa = new owa_php(); |
global $owaSiteID; | global $owaSiteID; |
$owa->setSiteId($owaSiteID); | $owa->setSiteId($owaSiteID); |
$owa->setPageTitle($pageTitle); | $owa->setPageTitle($pageTitle); |
$owa->setPageType($pageType); | $owa->setPageType($pageType); |
$owa->trackPageView(); | $owa->trackPageView(); |
$owa->placeHelperPageTags(); | $owa->placeHelperPageTags(); |
} | } |
if ($opendiv) { | if ($opendiv) { |
echo '<div data-role="page"> | echo '<div data-role="page"> |
<script> | <script> |
$(document).ready(function () | $(document).ready(function () |
{ | { |
document.title = "' . $pageTitle . '"; | document.title = "' . $pageTitle . '"; |
}); | }); |
</script> | </script> |
<div data-role="header"> | <div data-role="header"> |
<h1>' . $pageTitle . '</h1> | <h1>' . $pageTitle . '</h1> |
</div><!-- /header --> | </div><!-- /header --> |
<div data-role="content"> '; | <div data-role="content"> '; |
} | } |
} | } |
function include_footer() | function include_footer() |
{ | { |
if ($geolocate && isset($_SESSION['lat'])) { | if ($geolocate && isset($_SESSION['lat'])) { |
echo "<script> | echo "<script> |
$('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); | $('#here').click(function(event) { $('#geolocate').val(doAJAXrequestForGeolocSessionHere()); return false;}); |
$('#here').show(); | $('#here').show(); |
</script>"; | </script>"; |
} | } |
echo '<div id="footer"><a href="about.php">About/Contact Us</a> <a href="feedback.php">Feedback/Bug Report</a></a>'; | echo '<div id="footer"><a href="about.php">About/Contact Us</a> <a href="feedback.php">Feedback/Bug Report</a></a>'; |
echo '</div>'; | echo '</div>'; |
} | } |
function timePlaceSettings($geolocate = false) | function timePlaceSettings($geolocate = false) |
{ | { |
global $service_periods; | global $service_periods; |
$geoerror = false; | $geoerror = false; |
if ($geolocate == true) { | if ($geolocate == true) { |
$geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; | $geoerror = !isset($_SESSION['lat']) || !isset($_SESSION['lat']) || $_SESSION['lat'] == "" || $_SESSION['lon'] == ""; |
} | } |
if ($geoerror) { | if ($geoerror) { |
echo '<div class="error">Sorry, but your location could not currently be detected. | echo '<div class="error">Sorry, but your location could not currently be detected. |
Please allow location permission, wait for your location to be detected, | Please allow location permission, wait for your location to be detected, |
or enter an address/co-ordinates in the box below.</div>'; | or enter an address/co-ordinates in the box below.</div>'; |
} | } |
echo '<div data-role="collapsible" data-collapsed="' . !$geoerror . '"> | echo '<div data-role="collapsible" data-collapsed="' . !$geoerror . '"> |
<h3>Change Time/Place (' . $_SESSION['time'] . ' '.ucwords(service_period()).')...</h3> | <h3>Change Time/Place (' . (isset($_SESSION['time']) ? $_SESSION['time'] : "Current Time,") . ' '.ucwords(service_period()).')...</h3> |
<form action="" method="post"> | <form action="" method="post"> |
<div class="ui-body"> | <div class="ui-body"> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="geolocate"> Current Location: </label> | <label for="geolocate"> Current Location: </label> |
<input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> | <input type="text" id="geolocate" name="geolocate" value="' . (isset($_SESSION['lat']) && isset($_SESSION['lon']) ? $_SESSION['lat'] . "," . $_SESSION['lon'] : "Enter co-ordinates or address here") . '"/> <a href="#" style="display:none" name="here" id="here"/>Here?</a> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="time"> Time: </label> | <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"/>Current Time?</a> |
</div> | </div> |
<div data-role="fieldcontain"> | <div data-role="fieldcontain"> |
<label for="service_period"> Service Period: </label> | <label for="service_period"> Service Period: </label> |
<select name="service_period">'; | <select name="service_period">'; |
foreach ($service_periods as $service_period) { | foreach ($service_periods as $service_period) { |
echo "<option value=\"$service_period\"" . (service_period() === $service_period ? "SELECTED" : "") . '>' . ucwords($service_period) . '</option>'; | echo "<option value=\"$service_period\"" . (service_period() === $service_period ? "SELECTED" : "") . '>' . ucwords($service_period) . '</option>'; |
} | } |
echo '</select> | echo '</select> |
<a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> | <a href="#" style="display:none" name="currentPeriod" id="currentPeriod"/>Current Period?</a> |
</div> | </div> |
<input type="submit" value="Update"/> | <input type="submit" value="Update"/> |
</form> | </form> |
</div></div>'; | </div></div>'; |
} | } |
?> | ?> |
#!/usr/bin/python2.5 | #!/usr/bin/python2.5 |
# Copyright (C) 2007 Google Inc. | # Copyright (C) 2007 Google Inc. |
# | # |
# Licensed under the Apache License, Version 2.0 (the "License"); | # Licensed under the Apache License, Version 2.0 (the "License"); |
# you may not use this file except in compliance with the License. | # you may not use this file except in compliance with the License. |
# You may obtain a copy of the License at | # You may obtain a copy of the License at |
# | # |
# http://www.apache.org/licenses/LICENSE-2.0 | # http://www.apache.org/licenses/LICENSE-2.0 |
# | # |
# Unless required by applicable law or agreed to in writing, software | # Unless required by applicable law or agreed to in writing, software |
# distributed under the License is distributed on an "AS IS" BASIS, | # distributed under the License is distributed on an "AS IS" BASIS, |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
# See the License for the specific language governing permissions and | # See the License for the specific language governing permissions and |
# limitations under the License. | # limitations under the License. |
""" | """ |
An example application that uses the transitfeed module. | An example application that uses the transitfeed module. |
You must provide a Google Maps API key. | You must provide a Google Maps API key. |
""" | """ |
import BaseHTTPServer, sys, urlparse | import BaseHTTPServer, sys, urlparse |
import bisect | import bisect |
from gtfsscheduleviewer.marey_graph import MareyGraph | from gtfsscheduleviewer.marey_graph import MareyGraph |
import gtfsscheduleviewer | import gtfsscheduleviewer |
import mimetypes | import mimetypes |
import os.path | import os.path |
import re | import re |
import signal | import signal |
import simplejson | import simplejson |
import socket | import socket |
import time | import time |
import datetime | import datetime |
import transitfeed | import transitfeed |
from transitfeed import util | from transitfeed import util |
import urllib | import urllib |
# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break | # By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break |
# raise a KeyboardInterrupt. | # raise a KeyboardInterrupt. |
if hasattr(signal, 'SIGBREAK'): | if hasattr(signal, 'SIGBREAK'): |
signal.signal(signal.SIGBREAK, signal.default_int_handler) | signal.signal(signal.SIGBREAK, signal.default_int_handler) |
mimetypes.add_type('text/plain', '.vbs') | mimetypes.add_type('text/plain', '.vbs') |
class ResultEncoder(simplejson.JSONEncoder): | class ResultEncoder(simplejson.JSONEncoder): |
def default(self, obj): | def default(self, obj): |
try: | try: |
iterable = iter(obj) | iterable = iter(obj) |
except TypeError: | except TypeError: |
pass | pass |
else: | else: |
return list(iterable) | return list(iterable) |
return simplejson.JSONEncoder.default(self, obj) | return simplejson.JSONEncoder.default(self, obj) |
# Code taken from | # Code taken from |
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt | # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt |
# An alternate approach is shown at | # An alternate approach is shown at |
# http://mail.python.org/pipermail/python-list/2003-July/212751.html | # 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 | # but it requires multiple threads. A sqlite object can only be used from one |
# thread. | # thread. |
class StoppableHTTPServer(BaseHTTPServer.HTTPServer): | class StoppableHTTPServer(BaseHTTPServer.HTTPServer): |
def server_bind(self): | def server_bind(self): |
BaseHTTPServer.HTTPServer.server_bind(self) | BaseHTTPServer.HTTPServer.server_bind(self) |
self.socket.settimeout(1) | self.socket.settimeout(1) |
self._run = True | self._run = True |
def get_request(self): | def get_request(self): |
while self._run: | while self._run: |
try: | try: |
sock, addr = self.socket.accept() | sock, addr = self.socket.accept() |
sock.settimeout(None) | sock.settimeout(None) |
return (sock, addr) | return (sock, addr) |
except socket.timeout: | except socket.timeout: |
pass | pass |
def stop(self): | def stop(self): |
self._run = False | self._run = False |
def serve(self): | def serve(self): |
while self._run: | while self._run: |
self.handle_request() | self.handle_request() |
def StopToTuple(stop): | def StopToTuple(stop): |
"""Return tuple as expected by javascript function addStopMarkerFromList""" | """Return tuple as expected by javascript function addStopMarkerFromList""" |
return (stop.stop_id, stop.stop_name, float(stop.stop_lat), | return (stop.stop_id, stop.stop_name, float(stop.stop_lat), |
float(stop.stop_lon), stop.location_type, stop.stop_code) | float(stop.stop_lon), stop.location_type, stop.stop_code) |
def StopZoneToTuple(stop): | def StopZoneToTuple(stop): |
"""Return tuple as expected by javascript function addStopMarkerFromList""" | """Return tuple as expected by javascript function addStopMarkerFromList""" |
return (stop.stop_id, stop.stop_name, float(stop.stop_lat), | return (stop.stop_id, stop.stop_name, float(stop.stop_lat), |
float(stop.stop_lon), stop.location_type, stop.stop_code, stop.zone_id) | float(stop.stop_lon), stop.location_type, stop.stop_code, stop.zone_id) |
class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
cache = {} | cache = {} |
def do_GET(self): | def do_GET(self): |
scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) | scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) |
parsed_params = {} | parsed_params = {} |
for k in params.split('&'): | for k in params.split('&'): |
k = urllib.unquote(k) | k = urllib.unquote(k) |
if '=' in k: | if '=' in k: |
k, v = k.split('=', 1) | k, v = k.split('=', 1) |
parsed_params[k] = unicode(v, 'utf8') | parsed_params[k] = unicode(v, 'utf8') |
else: | else: |
parsed_params[k] = '' | parsed_params[k] = '' |
if path == '/': | if path == '/': |
return self.handle_GET_home() | return self.handle_GET_home() |
m = re.match(r'/json/([a-z]{1,64})', path) | m = re.match(r'/json/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_json_GET_%s' % m.group(1) | handler_name = 'handle_json_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return self.handle_json_wrapper_GET(handler, parsed_params, handler_name) | return self.handle_json_wrapper_GET(handler, parsed_params, handler_name) |
# Restrict allowable file names to prevent relative path attacks etc | # 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) | m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) |
if m and m.group(1): | if m and m.group(1): |
try: | try: |
f, mime_type = self.OpenFile(m.group(1)) | f, mime_type = self.OpenFile(m.group(1)) |
return self.handle_static_file_GET(f, mime_type) | return self.handle_static_file_GET(f, mime_type) |
except IOError, e: | except IOError, e: |
print "Error: unable to open %s" % m.group(1) | print "Error: unable to open %s" % m.group(1) |
# Ignore and treat as 404 | # Ignore and treat as 404 |
m = re.match(r'/([a-z]{1,64})', path) | m = re.match(r'/([a-z]{1,64})', path) |
if m: | if m: |
handler_name = 'handle_GET_%s' % m.group(1) | handler_name = 'handle_GET_%s' % m.group(1) |
handler = getattr(self, handler_name, None) | handler = getattr(self, handler_name, None) |
if callable(handler): | if callable(handler): |
return handler(parsed_params) | return handler(parsed_params) |
return self.handle_GET_default(parsed_params, path) | return self.handle_GET_default(parsed_params, path) |
def OpenFile(self, filename): | def OpenFile(self, filename): |
"""Try to open filename in the static files directory of this server. | """Try to open filename in the static files directory of this server. |
Return a tuple (file object, string mime_type) or raise an exception.""" | Return a tuple (file object, string mime_type) or raise an exception.""" |
(mime_type, encoding) = mimetypes.guess_type(filename) | (mime_type, encoding) = mimetypes.guess_type(filename) |
assert mime_type | assert mime_type |
# A crude guess of when we should use binary mode. Without it non-unix | # A crude guess of when we should use binary mode. Without it non-unix |
# platforms may corrupt binary files. | # platforms may corrupt binary files. |
if mime_type.startswith('text/'): | if mime_type.startswith('text/'): |
mode = 'r' | mode = 'r' |
else: | else: |
mode = 'rb' | mode = 'rb' |
return open(os.path.join(self.server.file_dir, filename), mode), mime_type | return open(os.path.join(self.server.file_dir, filename), mode), mime_type |
def handle_GET_default(self, parsed_params, path): | def handle_GET_default(self, parsed_params, path): |
self.send_error(404) | self.send_error(404) |
def handle_static_file_GET(self, fh, mime_type): | def handle_static_file_GET(self, fh, mime_type): |
content = fh.read() | content = fh.read() |
self.send_response(200) | self.send_response(200) |
self.send_header('Content-Type', mime_type) | self.send_header('Content-Type', mime_type) |
self.send_header('Content-Length', str(len(content))) | self.send_header('Content-Length', str(len(content))) |
self.end_headers() | self.end_headers() |
self.wfile.write(content) | self.wfile.write(content) |
def AllowEditMode(self): | def AllowEditMode(self): |
return False | return False |
def handle_GET_home(self): | def handle_GET_home(self): |
schedule = self.server.schedule | schedule = self.server.schedule |
(min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() | (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() |
forbid_editing = ('true', 'false')[self.AllowEditMode()] | forbid_editing = ('true', 'false')[self.AllowEditMode()] |
agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') | agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') |
key = self.server.key | key = self.server.key |
host = self.server.host | host = self.server.host |
# A very simple template system. For a fixed set of values replace [xxx] | # A very simple template system. For a fixed set of values replace [xxx] |
# with the value of local variable xxx | # with the value of local variable xxx |
f, _ = self.OpenFile('index.html') | f, _ = self.OpenFile('index.html') |
content = f.read() | content = f.read() |
for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', | for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', |
'host', 'forbid_editing'): |