3 // Copyright 2010 Guillaume Cottenceau.
5 // Licensed under the Apache License, Version 2.0 (the "License"); you
6 // may not use this site or the software running this site except in
7 // compliance with the License. You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, this is
12 // provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
13 // KIND, either express or implied. See the License for the specific
14 // language governing permissions and limitations under the
17 ini_set("track_errors", 1);
18 ini_set('display_errors', 0);
22 // Helper function for fatal errors
23 function fatal($msg) {
24 echo "<h2>Error</h2>\n";
26 echo "</body></html>";
31 $host = 'api.hostip.info';
33 $path = '/get_html.php?position=true&ip=' . $_SERVER['REMOTE_ADDR'];
35 $fp = @fsockopen($host, $port, $errno, $errstr);
37 fatal("<p>Unable to open connection to <tt>$host</tt> ".
38 "(port <tt>$port</tt>):</p><pre>$errstr</pre>");
40 fwrite($fp, "GET $path HTTP/1.0\r\n");
41 fwrite($fp, "Host: $host:$port\r\n");
47 $buf .= fread($fp, 8192);
48 // Parse the HTTP answer and try to extract response code,
50 $answer = parse_answer($buf);
52 // We need to discover Content-Length, to know when server
53 // finishes sending data
55 if ($answer[0] == 200)
56 $length = $answer[1]['content-length'];
59 // When length is available, we can check if response has
60 // been fully transmitted; this is the case when all what
61 // we received equals the headers plus the full contents.
63 if (strlen_b($buf) == strlen_b($answer[3]) + $length)
71 $latitude = $longitude = $zoom = 0;
72 if (preg_match('/Latitude: (\S+)/', $body, $matches)) {
73 $latitude = $matches[1];
76 if (preg_match('/Longitude: (\S+)/', $body, $matches)) {
77 $longitude = $matches[1];
79 if (($latitude == 0 || $longitude == 0) && preg_match('/Country: .*?\((\S{2})\)/', $body, $matches)) {
80 $country = $matches[1];
81 include('countries.phpi');
82 $latitude = $countries[$country][0];
83 $longitude = $countries[$country][1];
87 // PHP's strlen should return the length of a string in bytes,
88 // except when using multibyte strings, in which case
89 // mb_orig_strlen must be used (in case strlen was overloaded
91 function strlen_b($str) {
92 if (function_exists('mb_orig_strlen')) {
93 return mb_orig_strlen($str);
99 // Parse an HTTP answer to extract response code, headers and body
100 // Returns an array containing: response code, headers, body, raw headers
101 function parse_answer($answer) {
103 // This first pattern matching allows to separate first line
104 // (server response status), headers, and data contents
105 if (ereg("^(([^\n]+)\r\n(.*)\r\n\r\n)(.*)", $answer, $regs)) {
106 $full_headers = $regs[1];
107 $response = $regs[2];
108 $headers_string = $regs[3];
110 // Parse first line (server response status)
111 if (ereg("^HTTP/[0-9\.]+ ([0-9]+)", $response, $regs)) {
112 $response_code = $regs[1];
114 fatal("<p>Unable to parse response line <tt>$response</tt> ".
115 "from the server.</p>");
117 // Parse headers and build a hash with them
118 foreach (split("\r\n", $headers_string) as $line) {
119 if (ereg("^([^:]+): (.*)", $line, $regs)) {
120 $headers[strtolower($regs[1])] = $regs[2];
122 fatal("<p>Unable to parse header line <tt>$line</tt> ".
124 "All headers:</p><pre>$headers_string</pre>");
128 // Return -1 as response code if parsing was not possible
131 return array($response_code, $headers, $body, $full_headers);
138 <title>Routes Compare</title>
139 <link rel="stylesheet" type="text/css" media="screen" href="style.css"/>
140 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
141 <script type="text/javascript" src="prototype.js"></script>
142 <script type="text/javascript" src="effects.js"></script>
143 <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
144 <script type="text/javascript" src="googlemaps.js.php"></script>
145 <script type="text/javascript">
147 // Copyright (c) Guillaume Cottenceau and licensed under the Apache 2.0 License
151 var places = new Array();
152 var geocoder = new google.maps.Geocoder();
153 var directions_service = new google.maps.DirectionsService();
154 var info_window = null;
156 var travelmode = google.maps.DirectionsTravelMode.DRIVING;
158 function reload(new_places) {
159 for (var i = 0; i < places.length; i++) {
160 places[i].marker.setMap(null);
161 places[i].directions_display.setMap(null);
163 places = new Array();
164 document.getElementById("resultslist").innerHTML = '';
165 for (var i = 0; i < new_places.length; i++) {
166 createPlace(new_places[i].latlng, new_places[i].name);
170 function travelmodeChanged() {
171 travelmode = eval(document.getElementById("travelmode").value);
175 function showDirectionCapture(i) {
176 var request = { origin: new google.maps.LatLng(mylat, mylng),
177 destination: places[i].latlng,
178 travelMode: travelmode };
179 directions_service.route(request, function(result, status) {
180 if (status == google.maps.DirectionsStatus.OK) {
181 places[i].directions_display.setMap(map);
182 places[i].directions_display.setDirections(result);
183 displayDirectionsMoreinfo(result.routes[0], document.getElementById("directions" + ( 1 + i )));
189 if (document.getElementById("fitmap").checked) {
190 map.fitBounds(bounds);
194 function showDirections() {
195 if (places.length > 0) {
196 bounds = new google.maps.LatLngBounds();
197 bounds.extend(new google.maps.LatLng(mylat, mylng));
199 for (var i = 0; i < places.length; i++) {
200 if (!places[i].directions_display.getMap()) {
201 showDirectionCapture(i);
203 bounds.extend(places[i].latlng);
208 function showDel(number) {
209 document.getElementById("delete" + number).style.visibility = 'visible';
212 function hideDel(number) {
213 document.getElementById("delete" + number).style.visibility = 'hidden';
216 function del(number) {
217 var new_places = new Array();
218 for (var i = 0; i < places.length; i++) {
219 if (i == number - 1) {
220 places[i].marker.setMap(null);
221 places[i].directions_display.setMap(null);
223 new_places.push(places[i]);
229 function createPlace(latlng, name) {
230 var number = places.length + 1;
231 var iconname = 'icon' + ( 7 + number );
232 var marker = new google.maps.Marker({ position: latlng,
234 icon:getIcon(iconname),
235 shadow:getShadow(iconname) });
237 document.getElementById("resultslist").innerHTML += "<li onmouseover='showDel(" + number + ")' onmouseout='hideDel(" + number + ")'><img class='iconwithtext' src='images/" + iconname + ".png'/> " + name
238 + "<div style='float:right; padding:3; visibility:hidden' id='delete" + number
239 + "'><a href='#' onclick='del(" + number + ")'><img src='images/bin.png'/></a></div>"
240 + "<br/><span id='directions" + number + "'></span></li>";
241 var directions_display = new google.maps.DirectionsRenderer({ preserveViewport: true, suppressMarkers: true, draggable: true });
242 google.maps.event.addListener(directions_display, "directions_changed", function() {
243 displayDirectionsMoreinfo(directions_display.getDirections().routes[0], document.getElementById("directions" + number ));
245 places.push({marker:marker, latlng:latlng, name:name, directions_display:directions_display});
254 new Effect.Fade(document.getElementById('newbie'), {duration: 0.4});
255 new Effect.Fade(document.getElementById('usecases'), {duration: 0.4});
256 var address = document.getElementById('address').value;
257 geocoder.geocode({ 'address': address },
258 function(results, status) {
259 if (status == google.maps.GeocoderStatus.OK) {
260 createPlace(results[0].geometry.location, address);
261 document.getElementById('address').value = '';
262 document.getElementById('address').focus();
264 document.getElementById('submitshortresult').innerHTML = "<?php echo t('address.not.found') ?>";
265 document.getElementById('submitshortresult').style.display = '';
266 setTimeout('new Effect.Fade(document.getElementById("submitshortresult"), {duration: 0.4})', 1000);
272 var link = "#me=" + mylat + ";" + mylng;
273 for (var i = 0; i < places.length; i++) {
274 link += "&p=" + places[i].latlng.lat() + ";" + places[i].latlng.lng() + ";" + encodeURI(places[i].name);
276 document.getElementById('savediv').style.display = '';
277 var save = document.getElementById('save');
278 save.value = 'http://routes-compare.zarb.org/' + link;
284 var me = new google.maps.Marker({position: new google.maps.LatLng(mylat, mylng),
287 icon: getIcon('icon31'),
288 shadow: getShadow('icon31')});
290 google.maps.event.addListener(me, "dragend", function(mouseEvent) {
291 mylat = mouseEvent.latLng.lat();
292 mylng = mouseEvent.latLng.lng();
295 map.setCenter(new google.maps.LatLng(mylat, mylng));
299 function initialize() {
300 map = new google.maps.Map(document.getElementById("mapbox"),
301 { mapTypeId: google.maps.MapTypeId.ROADMAP,
306 var all_params = location.href.split("#")
307 if (all_params.length > 1 && all_params[1].length > 0) {
308 var params = all_params[1].split("&");
309 for (i = 0; i < params.length; i++) {
310 var keyvalue = params[i].split("=");
311 var values = keyvalue[1].split(";");
312 if (keyvalue[0] == 'me') {
315 } else if (keyvalue[0] == 'p') {
316 createPlace(new google.maps.LatLng(values[0], values[1]), decodeURI(values[2]));
324 mylat = <?php echo $latitude ?>;
325 mylng = <?php echo $longitude ?>;
326 var baseinfomessage = '<?php echo t('geolocated') ?>';
330 var baseinfomessage = '<?php echo t('not.geolocated') ?>';
334 map.setZoom(<?php echo $zoom ?>);
336 info_window = new google.maps.InfoWindow({ content: baseinfomessage + '<?php echo t('home.icon.move.possible') ?>' });
337 info_window.open(map, me);
338 if (!document.cookie || document.cookie.indexOf("not-a-newbie") == -1) {
339 document.getElementById("newbie").style.display = '';
341 var expires = new Date(new Date().getTime() + (10 * 86400000)); // 10 days
342 document.cookie = "not-a-newbie=true"
343 + "; expires=" + expires.toGMTString()
351 <body onload="initialize()">
353 <div id="mainbox" style="height: 100%">
355 <div id="debugbox"></div>
357 <div style="height: 2em">
358 <div style="float: right">
359 <?php echo t('travelmode') ?>
360 <select id="travelmode" onchange="travelmodeChanged()">
361 <option value="google.maps.DirectionsTravelMode.DRIVING"><?php echo t('travelmode.driving') ?></option>
362 <option value="google.maps.DirectionsTravelMode.WALKING"><?php echo t('travelmode.walking') ?></option>
363 <!-- doesn't work <option value="google.maps.DirectionsTravelMode.BICYCLING">Bicycling</option> -->
366 <input type="checkbox" id="fitmap" checked="true" onchange="fitmap()"><?php echo t('fit.to.elements') ?>
368 <a href="#" onclick="save()">
369 <?php echo t('save.this.page') ?>
370 <img src="images/save.png" class="iconwithtext"/>
373 <?php if ($language != 'en') { ?>
374 <a href="?language=en"><img src="images/en.png" class="iconwithtext" style="opacity:0.4;filter:alpha(opacity=40)"/></a>
376 <a href="?language=en"><img src="images/en.png" class="iconwithtext"/></a>
378 <?php if ($language != 'fr') { ?>
379 <a href="?language=fr"><img src="images/fr.png" class="iconwithtext" style="opacity:0.4;filter:alpha(opacity=40)"/></a>
381 <a href="?language=fr"><img src="images/fr.png" class="iconwithtext"/></a>
383 <div id="savediv" style="display: none; position:absolute; right:1em; top:3em; background:#E0E0FF; border:solid 1px black; padding:0.5em; z-index:1">
384 <?php echo t('save.page.expl') ?>
386 <input type="text" id="save" size="40"/>
388 <div style="float:right"><a href="#" onclick="javascript:new Effect.Fade(document.getElementById('savediv'), {duration: 0.4})"><?php echo t('Okay') ?></a></div>
392 <form action="javascript:submit()">
393 <?php echo t('address') ?>
395 <input type="text" size="32" id="address"/>
396 <script type="text/javascript">
397 document.getElementById('address').focus();
399 <input type="submit" value="<?php echo t('show.route') ?>"/>
400 <span id="submitshortresult" style="color: red">
407 <div class="containermainbox">
408 <div style="float: right; width: 75%; height: 100%">
409 <div id="mapbox" style="width: 100%; height: 95%">
411 <div id="usecases" style="display:none; background-color: #F77; border: solid 1px blue; position:fixed; top:10%; left:30%; right:30%; z-index:1">
412 <p style="margin:1em">
413 <?php echo t('use.cases.title') ?>
415 <p style="margin:1em">
416 <?php echo t('use.case.val') ?>
418 <p style="margin:1em">
419 <?php echo t('use.case.riviera') ?>
421 <div style="float:right; margin:1em"><a href="#" onclick="javascript:new Effect.Fade(document.getElementById('usecases'), {duration: 0.4})"><?php echo t('Okay') ?></a></div>
423 <div style="float:right; font-size:70%; margin-top:3px">
425 <?php echo t('bottomstuff') ?>
429 <div id="newbie" style="display: none; background-color: pink; border: solid 1px blue; position:absolute; width:20%; margin:1.5em">
431 <img src="images/top.png"/>
433 <p align="right" style="margin-right:1em; margin-top:-1em">
434 <?php echo t('add.addess.top') ?>
438 <img src="images/right.png"/>
440 <p align="right" style="margin-right:1em; margin-top:-1em">
441 <?php echo t('routes.shown') ?>
445 <p align="right" style="margin-right:1em; margin-top:-1em">
446 <a href="#" onclick="javascript:new Effect.Fade(document.getElementById('newbie'), {duration: 0.4})"><?php echo t('Okay') ?></a>
449 <p style="margin:1em">
450 <a href="#" onclick="javascript:new Effect.Appear(document.getElementById('usecases'), {duration: 0.4})"><?php echo t('show.use.cases') ?></a>
453 <ul id="resultslist">