i18n
[maps-routes-comparison] / index.php
1 <?php
2
3 // Copyright 2010 Guillaume Cottenceau.
4 // 
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
8 // 
9 //            http://www.apache.org/licenses/LICENSE-2.0
10 // 
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
15 // License.
16
17 ini_set("track_errors", 1);
18 ini_set('display_errors', 0);
19
20 include("i18n.phpi");
21
22 // Helper function for fatal errors
23 function fatal($msg) {
24     echo "<h2>Error</h2>\n";
25     echo "$msg\n";
26     echo "</body></html>";
27     exit;
28
29 }
30
31 $host = 'api.hostip.info';
32 $port = 80;
33 $path = '/get_html.php?position=true&ip=' . $_SERVER['REMOTE_ADDR'];
34
35 $fp = @fsockopen($host, $port, $errno, $errstr);
36 if (!$fp)
37     fatal("<p>Unable to open connection to <tt>$host</tt> ".
38           "(port <tt>$port</tt>):</p><pre>$errstr</pre>");
39
40 fwrite($fp, "GET $path HTTP/1.0\r\n");
41 fwrite($fp, "Host: $host:$port\r\n");
42 fwrite($fp, "\r\n");
43
44 $buf = '';
45 $length = '';
46 while (!feof($fp)) {
47     $buf .= fread($fp, 8192);
48     // Parse the HTTP answer and try to extract response code,
49     // headers and body
50     $answer = parse_answer($buf);
51
52     // We need to discover Content-Length, to know when server
53     // finishes sending data
54     if (!$length) {
55         if ($answer[0] == 200)
56             $length = $answer[1]['content-length'];
57     }
58     
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.
62     if ($length) {
63         if (strlen_b($buf) == strlen_b($answer[3]) + $length)
64             break;
65     }
66 }
67
68 fclose($fp);
69 $body = $answer[2];
70
71 $latitude = $longitude = $zoom = 0;
72 if (preg_match('/Latitude: (\S+)/', $body, $matches)) {
73     $latitude = $matches[1];
74     $zoom = 8;
75 }
76 if (preg_match('/Longitude: (\S+)/', $body, $matches)) {
77     $longitude = $matches[1];
78 }
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];
84     $zoom = 5;
85 }
86
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
90 // with mb_strlen).
91 function strlen_b($str) {
92     if (function_exists('mb_orig_strlen')) {
93         return mb_orig_strlen($str);
94     } else {
95         return strlen($str);
96     }
97 }
98
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) {
102
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];
109         $body           = $regs[4];
110         // Parse first line (server response status)
111         if (ereg("^HTTP/[0-9\.]+ ([0-9]+)", $response, $regs)) {
112             $response_code = $regs[1];
113         } else {
114             fatal("<p>Unable to parse response line <tt>$response</tt> ".
115                   "from the server.</p>");
116         }
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];
121             } else {
122                 fatal("<p>Unable to parse header line <tt>$line</tt> ".
123                       "from the server. ".
124                       "All headers:</p><pre>$headers_string</pre>");
125             }
126         }
127     } else {
128         // Return -1 as response code if parsing was not possible
129         return array(-1);
130     }
131     return array($response_code, $headers, $body, $full_headers);
132 }
133
134 ?>
135
136 <html>
137 <head>
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">
146
147       // Copyright (c) Guillaume Cottenceau and licensed under the Apache 2.0 License
148
149       var mylat, mylng;
150       var map;
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;
155       var bounds;
156       var travelmode = google.maps.DirectionsTravelMode.DRIVING;
157
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);
162           }
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);
167           }
168       }
169
170       function travelmodeChanged() {
171           travelmode = eval(document.getElementById("travelmode").value);
172           reload(places);
173       }
174
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 )));
184               }
185           });
186       }
187       
188       function fitmap() {
189           if (document.getElementById("fitmap").checked) {
190               map.fitBounds(bounds);
191           }
192       }
193
194       function showDirections() {
195           if (places.length > 0) {
196               bounds = new google.maps.LatLngBounds();
197               bounds.extend(new google.maps.LatLng(mylat, mylng));
198           }
199           for (var i = 0; i < places.length; i++) {
200               if (!places[i].directions_display.getMap()) {
201                   showDirectionCapture(i);
202               }
203               bounds.extend(places[i].latlng);
204           }
205           fitmap();
206       }
207
208       function showDel(number) {
209           document.getElementById("delete" + number).style.visibility = 'visible';
210       }
211
212       function hideDel(number) {
213           document.getElementById("delete" + number).style.visibility = 'hidden';
214       }
215
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);
222               } else {
223                   new_places.push(places[i]);
224               }
225           }
226           reload(new_places);
227       }
228
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,
233                                                 title:name,
234                                                 icon:getIcon(iconname),
235                                                 shadow:getShadow(iconname) });
236           marker.setMap(map);
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 ));
244           });
245           places.push({marker:marker, latlng:latlng, name:name, directions_display:directions_display});
246           showDirections();
247       }
248
249       function submit() {
250           if (info_window) {
251               info_window.close();
252               info_window = null;
253           }
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();
263                                } else {
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);
267                                }
268                            });
269       }
270
271       function save() {
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);
275           }
276           document.getElementById('savediv').style.display = '';
277           var save = document.getElementById('save');
278           save.value = 'http://routes-compare.zarb.org/' + link;
279           save.focus();
280           save.select();
281       }
282
283       function startUp() {
284           var me = new google.maps.Marker({position: new google.maps.LatLng(mylat, mylng),
285                                            title: 'Me',
286                                            draggable: true,
287                                            icon: getIcon('icon31'),
288                                            shadow: getShadow('icon31')});
289           me.setMap(map);
290           google.maps.event.addListener(me, "dragend", function(mouseEvent) {
291                   mylat = mouseEvent.latLng.lat();
292                   mylng = mouseEvent.latLng.lng();
293                   reload(places);
294               });
295           map.setCenter(new google.maps.LatLng(mylat, mylng));
296           return me;
297       }
298                          
299       function initialize() {
300           map = new google.maps.Map(document.getElementById("mapbox"),
301                                     { mapTypeId: google.maps.MapTypeId.ROADMAP,
302                                       zoom: 2 });
303
304           mylat = 0;
305           mylng = 0;
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') {
313                       mylat = values[0];
314                       mylng = values[1];
315                   } else if (keyvalue[0] == 'p') {
316                       createPlace(new google.maps.LatLng(values[0], values[1]), decodeURI(values[2]));
317                   }
318               }
319               startUp();
320           } else {
321               <?php
322                   if ($latitude) {
323                ?>
324               mylat = <?php echo $latitude ?>;
325               mylng = <?php echo $longitude ?>;
326               var baseinfomessage = '<?php echo t('geolocated') ?>';
327               <?php
328                   } else {
329                ?>
330               var baseinfomessage = '<?php echo t('not.geolocated') ?>';
331               <?php
332                   }
333                ?>
334               map.setZoom(<?php echo $zoom ?>);
335               me = startUp();
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 = '';
340               }
341               var expires = new Date(new Date().getTime() + (10 * 86400000));  // 10 days
342               document.cookie = "not-a-newbie=true"
343                                 + "; expires=" + expires.toGMTString()
344                                 + "; path=/";
345           }
346       }
347
348     </script>
349 </head>
350
351 <body onload="initialize()">
352
353   <div id="mainbox" style="height: 100%">
354
355     <div id="debugbox"></div>
356
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> -->
364         </select>
365         - 
366         <input type="checkbox" id="fitmap" checked="true" onchange="fitmap()"><?php echo t('fit.to.elements') ?>
367         - 
368         <a href="#" onclick="save()">
369           <?php echo t('save.this.page') ?>
370           <img src="images/save.png" class="iconwithtext"/>
371         </a>
372         -
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>
375         <?php } else { ?>
376           <a href="?language=en"><img src="images/en.png" class="iconwithtext"/></a>
377         <?php } ?>
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>
380         <?php } else { ?>
381           <a href="?language=fr"><img src="images/fr.png" class="iconwithtext"/></a>
382         <?php } ?>
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') ?>
385           <br/>
386           <input type="text" id="save" size="40"/>
387           <br/>
388           <div style="float:right"><a href="#" onclick="javascript:new Effect.Fade(document.getElementById('savediv'), {duration: 0.4})"><?php echo t('Okay') ?></a></div>
389         </div>
390       </div>
391
392       <form action="javascript:submit()">
393       <?php echo t('address') ?>
394       
395       <input type="text" size="32" id="address"/>
396       <script type="text/javascript">
397         document.getElementById('address').focus();
398       </script>
399       <input type="submit" value="<?php echo t('show.route') ?>"/>
400       <span id="submitshortresult" style="color: red">
401       </span>
402       </form>
403
404     </div>
405
406
407     <div class="containermainbox">
408       <div style="float: right; width: 75%; height: 100%">
409          <div id="mapbox" style="width: 100%; height: 95%">
410          </div>
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') ?>
414            </p>
415            <p style="margin:1em">
416              <?php echo t('use.case.val') ?>
417            </p>
418            <p style="margin:1em">
419              <?php echo t('use.case.riviera') ?>
420            </p>
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>
422          </div>
423          <div style="float:right; font-size:70%; margin-top:3px">
424            <em>
425              <?php echo t('bottomstuff') ?>
426            </em>
427          </div>
428       </div>
429       <div id="newbie" style="display: none; background-color: pink; border: solid 1px blue; position:absolute; width:20%; margin:1.5em">
430         <p align="right">
431           <img src="images/top.png"/>
432         </p>
433         <p align="right" style="margin-right:1em; margin-top:-1em">
434           <?php echo t('add.addess.top') ?>
435         </p>
436         <br/>
437         <p align="right">
438           <img src="images/right.png"/>
439         </p>
440         <p align="right" style="margin-right:1em; margin-top:-1em">
441           <?php echo t('routes.shown') ?>
442         </p>
443         <br/>
444         <br/>
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>
447         </p>
448         <br/>
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>
451         </p>
452       </div>
453       <ul id="resultslist">
454       </ul>
455     </div>
456
457   </div>
458
459 </body>
460 </html>