diff options
-rw-r--r-- | LICENSE | 339 | ||||
-rwxr-xr-x | README | 32 | ||||
-rwxr-xr-x | auth.php | 117 | ||||
-rwxr-xr-x | config.php | 51 | ||||
-rwxr-xr-x | download.php | 221 | ||||
-rwxr-xr-x | export.php | 26 | ||||
-rwxr-xr-x | getpositions.php | 87 | ||||
-rwxr-xr-x | gettrips.php | 52 | ||||
-rwxr-xr-x | index.php | 186 | ||||
-rwxr-xr-x | lang.php | 82 | ||||
-rwxr-xr-x | logout.php | 30 | ||||
-rwxr-xr-x | main.css | 152 | ||||
-rwxr-xr-x | main.js | 412 | ||||
-rwxr-xr-x | requests.php | 268 | ||||
-rwxr-xr-x | trackme.sql | 128 |
15 files changed, 2183 insertions, 0 deletions
@@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. @@ -0,0 +1,32 @@ +This is a simple web viewer for GPS tracks uploaded with mobile client. +It is designed to work with Android version of great app TrackMe (http://www.luisespinosa.com/trackme_eng.html), +but it should be easy to adjust it for other clients. +Interface "look and feel" is based on TrackMe Display (http://forum.xda-developers.com/showthread.php?t=477394). +It currently uses Google Maps API, but work on OpenStreetMap is in progress. + +Live demo: +- http://flaa.fabiszewski.net/phptrackme/ + +Requirements: +- php 5 +- mysql +- browser with javascript enabled, cookies for authentication + +Features: +- simple +- allows live tracking +- track statistics +- altitudes graph +- multiple users +- user authentication +- Google Maps API v3 +- ajax +- server based configuration + +Todo +- OpenStreetMap API +- client based configuration +- write opensource client? + +License +- GPL diff --git a/auth.php b/auth.php new file mode 100755 index 0000000..ab4729c --- /dev/null +++ b/auth.php @@ -0,0 +1,117 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +require_once("config.php"); +require_once("lang.php"); +$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname); +if ($mysqli->connect_errno) { + printf("Connect failed: %s\n", $mysqli->connect_error); + exit(); +} +$auth = NULL; +if ($require_authentication) { + /* authentication */ + session_name('trackme'); + session_start(); + $sid = session_id(); + + $auth = (isset($_SESSION['auth']) ? $_SESSION['auth'] : ""); + $user = (isset($_REQUEST['user']) ? $_REQUEST['user'] : ""); + $pass = (isset($_REQUEST['pass']) ? md5($salt.$_REQUEST['pass']) : ""); + @$ssl = ($_SERVER['HTTPS'] == "" ? "http" : "https"); + $auth_error = (isset($_REQUEST['auth_error']) ? $_REQUEST['auth_error'] : 0); + + // not authenticated and username not submited + // load form + if ((!$auth) && (!$user)){ + print + '<!DOCTYPE html> + <html> + <head> + <title>'.$lang_title.'</title> + <meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> + <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> + <link rel="stylesheet" type="text/css" href="main.css"> + <script type="text/javascript"> + function focus() { + document.forms[0].elements[0].focus(); + } + </script> + </head> + <body onload="focus()"> + <div id="login"> + <div id="title">'.$lang_title.'</div> + <div id="subtitle">'.$lang_private.'</div> + <form action="index.php" method="post"> + '.$lang_username.':<br /> + <input type="text" name="user"><br /> + '.$lang_password.':<br /> + <input type="password" name="pass"><br /> + <br /> + <input type="submit" value="'.$lang_login.'"> + </form> + <div id="error">'.(($auth_error==1) ? $lang_authfail : "").'</div> + </div> + + </body> + </html>'; + $mysqli->close(); + exit; + } + + // username submited + if ((!$auth) && ($user)){ + $query = $mysqli->prepare("SELECT ID,username,password FROM users WHERE username=? LIMIT 1"); + $query->bind_param('s', $user); + $query->execute(); + $query->bind_result($rec_ID, $rec_user, $rec_pass); + $query->fetch(); + $query->free_result(); + //correct pass + if (($user==$rec_user) && ($pass==$rec_pass)) { + // login successful + //delete old session + $_SESSION = NULL; + session_destroy(); + // start new session + session_name('trackme'); + session_start(); + $_SESSION['auth'] = $rec_ID; + + $url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/index.php"); + header("Location: $ssl://$url"); + exit; + } else { + // unsuccessful + $error = "?auth_error=1"; + // destroy session + $_SESSION = NULL; + if (isset($_COOKIE[session_name('trackme')])) { + setcookie(session_name('trackme'),'',time()-42000,'/'); + } + session_destroy(); + $mysqli->close(); + $url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/index.php"); + header("Location: $ssl://$url$error"); + exit; + } + } + /* end of authentication */ +} +?> diff --git a/config.php b/config.php new file mode 100755 index 0000000..344efd6 --- /dev/null +++ b/config.php @@ -0,0 +1,51 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +$version = "1.0"; +// map drawing framework +// (gmaps = google maps, osm = openstreetmap (not supported yet)) +$mapapi = "gmaps"; +// you may add your google maps api key +// this is not obligatory by now +//$gkey = + +// db +$dbhost = ""; // mysql host, eg. localhost +$dbuser = ""; // database user +$dbpass = ""; // database pass +$dbname = ""; // database name +$salt = ""; // fill in random string here, it will increase security of password hashes + +// other +// require login/password authentication +// (0 = no, 1 = yes) +$require_authentication = 0; +// allow automatic registration of new users +// (0 = no, 1 = yes) +$allow_registration = 0; +// Default interval in seconds for live auto reload +$interval = 10; +// Default language +// (en, pl) +$lang = "en"; +// units +// (metric, imperial) +$units = "metric"; + +?> diff --git a/download.php b/download.php new file mode 100755 index 0000000..995f190 --- /dev/null +++ b/download.php @@ -0,0 +1,221 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +require_once("auth.php"); +$type = (isset($_REQUEST["type"]) ? $_REQUEST["type"] : "kml"); +$userid = ((isset($_REQUEST["userid"]) && is_numeric($_REQUEST["userid"])) ? $_REQUEST["userid"] : 0); +$trackid = ((isset($_REQUEST["trackid"]) && is_numeric($_REQUEST["trackid"])) ? $_REQUEST["trackid"] : 0); + +if ($units=="imperial") { + $factor_kmh = 0.62; //to mph + $unit_kmh = "mph"; + $factor_m = 3.28; // to feet + $unit_m = "ft"; + $factor_km = 0.62; // to miles + $unit_km = "mi"; +} +else { + $factor_kmh = 1; + $unit_kmh = "km/h"; + $factor_m = 1; + $unit_m = "m"; + $factor_km = 1; + $unit_km = "km"; +} + +function haversine_distance($lat1, $lon1, $lat2, $lon2) { + $lat1 = deg2rad($lat1); + $lon1 = deg2rad($lon1); + $lat2 = deg2rad($lat2); + $lon2 = deg2rad($lon2); + $latD = $lat2 - $lat1; + $lonD = $lon2 - $lon1; + $angle = 2*asin(sqrt(pow(sin($latD/2),2)+cos($lat1)*cos($lat2)*pow(sin($lonD/2),2))); + return $angle * 6371000; +} +function addStyle($xml,$name,$url) { + $xml->startElement("Style"); + $xml->writeAttribute("id", $name."Style"); + $xml->startElement("IconStyle"); + $xml->writeAttribute("id", $name."Icon"); + $xml->startElement("Icon"); + $xml->writeElement("href", $url); + $xml->endElement(); + $xml->endElement(); + $xml->endElement(); +} +function toHMS($s) { + $d = floor($s/86400); + $h = floor(($s%86400)/3600); + $m = floor((($s%86400)%3600)/60); + $s = (($s%86400)%3600)%60; + return (($d>0)?($d." d "):"").(substr("00".$h,-2)).":".(substr("00".$m,-2)).":".(substr("00".$s,-2)); +} + +if ($trackid>0 && $userid>0) { + $query = $mysqli->prepare("SELECT positions.ID,Latitude,Longitude,Altitude,Speed,Angle,DateOccurred,username,Name FROM positions LEFT JOIN users ON (positions.FK_Users_ID=users.ID) LEFT JOIN trips ON (positions.FK_Trips_ID=trips.ID) WHERE positions.FK_Users_ID=? AND positions.FK_Trips_ID=? ORDER BY positions.DateOccurred"); + $query->bind_param("ii", $userid, $trackid); + $query->execute(); + $query->store_result(); + $query->bind_result($positionid,$latitude,$longitude,$altitude,$speed,$angle,$dateoccured,$username,$trackname); + $query->fetch(); // take just one row to get trackname etc + $query->data_seek(0); // and reset result set + switch ($type) { + case "kml": + default: + header("Content-type: application/vnd.google-earth.kml+xml"); + header("Content-Disposition: attachment; filename=\"track$trackid.kml\""); + $xml = new XMLWriter(); + $xml->openURI("php://output"); + $xml->startDocument("1.0"); + $xml->startElement("kml"); + $xml->writeAttribute("xmlns", "http://earth.google.com/kml/2.1"); + $xml->setIndent(true); + $xml->startElement("Document"); + $xml->writeElement("name", $trackname); + // line style + $xml->startElement("Style"); + $xml->writeAttribute("id", "lineStyle"); + $xml->startElement("LineStyle"); + $xml->writeElement("color","7f0000ff"); + $xml->writeElement("width","4"); + $xml->endElement(); + $xml->endElement(); + // marker styles + addStyle($xml,"red","http://maps.google.com/mapfiles/markerA.png"); + addStyle($xml,"green","http://maps.google.com/mapfiles/marker_greenB.png"); + addStyle($xml,"gray","http://labs.google.com/ridefinder/images/mm_20_gray.png"); + $style = "#redStyle"; // for first element + $i = 0; + $totalMeters = 0; + $totalSeconds = 0; + while ($query->fetch()) { + $distance = (isset($prev_latitude))?haversine_distance($prev_latitude,$prev_longitude,$latitude,$longitude):0; + $prev_latitude = $latitude; + $prev_longitude = $longitude; + $seconds = (isset($prev_dateoccured))?(strtotime($dateoccured)-strtotime($prev_dateoccured)):0; + $prev_dateoccured = $dateoccured; + $totalMeters += $distance; + $totalSeconds += $seconds; + + if(++$i == $query->num_rows) { $style = "#greenStyle"; } // last element + $xml->startElement("Placemark"); + $xml->writeAttribute("id", $positionid); + //$xml->writeElement("name", $i); + $description = + "<div style=\"font-weight: bolder;padding-bottom: 10px;border-bottom: 1px solid gray;\">".$lang_user.": ".strtoupper($username)."<br />".$lang_track.": ".strtoupper($trackname). + "</div>". + "<div>". + "<div style=\"padding-top: 10px;\"><b>".$lang_time.":</b> ".$dateoccured."<br />". + (($speed)?"<b>".$lang_speed.":</b> ".round($speed*3.6,2*$factor_kmh)." ".$unit_kmh."<br />":""). + (($altitude != null)?"<b>".$lang_altitude.":</b> ".round($altitude*$factor_m)." ".$unit_m."<br />":""). + "<b>".$lang_ttime.":</b> ".toHMS($totalSeconds)."<br />". + "<b>".$lang_aspeed.":</b> ".(($totalSeconds!=0)?round($totalMeters/$totalSeconds*3.6*$factor_kmh,2):0)." ".$unit_kmh."<br />". + "<b>".$lang_tdistance.":</b> ".round($totalMeters/1000*$factor_km,2)." ".$unit_km."<br />"."</div>". + "<div style=\"font-size: smaller;padding-top: 10px;\">".$lang_point." ".$i." ".$lang_of." ".($query->num_rows-1)."</div>". + "</div>"; + $xml->startElement("description"); + $xml->writeCData($description); + $xml->endElement(); + $xml->writeElement("styleUrl", $style); + $xml->startElement("Point"); + $coordinate[$i] = $longitude.",".$latitude.(($altitude) ? ",".$altitude : ""); + $xml->writeElement("coordinates", $coordinate[$i]); + $xml->endElement(); + $xml->endElement(); + $style = "#grayStyle"; // other elements + } + $coordinates = implode("\n",$coordinate); + $xml->startElement("Placemark"); + $xml->writeElement("styleUrl", "#lineStyle"); + $xml->startElement("LineString"); + $xml->writeElement("coordinates", $coordinates); + $xml->endElement(); + $xml->endElement(); + + + $xml->endElement(); + $xml->endElement(); + $xml->endDocument(); + $xml->flush(); + + break; + + case "gpx": + header("Content-type: application/application/gpx+xm"); + header("Content-Disposition: attachment; filename=\"track$trackid.gpx\""); + $xml = new XMLWriter(); + $xml->openURI("php://output"); + $xml->startDocument("1.0"); + $xml->startElement("gpx"); + $xml->writeAttribute("xmlns", "http://www.topografix.com/GPX/1/1"); + $xml->writeAttribute("xmlns:gpxdata", "http://www.cluetrust.com/XML/GPXDATA/1/0"); + $xml->writeAttribute("creator", "phpTrackme"); + $xml->writeAttribute("version", "1.1"); + $xml->startElement("metadata"); + $xml->writeElement("name", $trackname); + $xml->writeElement("time", str_replace(" ","T",$dateoccured)); + $xml->endElement(); + $xml->startElement("trk"); + $xml->writeElement("name", $trackname); + $xml->startElement("trkseg"); + $i = 0; + $totalMeters = 0; + $totalSeconds = 0; + while ($query->fetch()) { + $distance = (isset($prev_latitude))?haversine_distance($prev_latitude,$prev_longitude,$latitude,$longitude):0; + $prev_latitude = $latitude; + $prev_longitude = $longitude; + $seconds = (isset($prev_dateoccured))?(strtotime($dateoccured)-strtotime($prev_dateoccured)):0; + $prev_dateoccured = $dateoccured; + $totalMeters += $distance; + $totalSeconds += $seconds; + $xml->startElement("trkpt"); + $xml->writeAttribute("lat", $latitude); + $xml->writeAttribute("lon", $longitude); + if($altitude) { $xml->writeElement("ele", $altitude); } + $xml->writeElement("time", str_replace(" ","T",$dateoccured)); + $xml->writeElement("name", ++$i); + $xml->startElement("desc"); + $description = + $lang_user.": ".strtoupper($username)." ".$lang_track.": ".strtoupper($trackname). + " ".$lang_time.": ".$dateoccured. + (($speed)?" ".$lang_speed.": ".round($speed*3.6,2*$factor_kmh)." ".$unit_kmh:""). + (($altitude != null)?" ".$lang_altitude.": ".round($altitude*$factor_m)." ".$unit_m:""). + " ".$lang_ttime.": ".toHMS($totalSeconds)."". + " ".$lang_aspeed.": ".(($totalSeconds!=0)?round($totalMeters/$totalSeconds*3.6*$factor_kmh,2):0)." ".$unit_kmh. + " ".$lang_tdistance.": ".round($totalMeters/1000*$factor_km,2)." ".$unit_km. + " ".$lang_point." ".$i." ".$lang_of." ".($query->num_rows-1); + $xml->writeCData($description); + $xml->endElement(); + $xml->endElement(); + } + $xml->endElement(); + $xml->endElement(); + $xml->endElement(); + $xml->endDocument(); + $xml->flush(); + + break; + } + $query->free_result(); + $query->close(); +} +$mysqli->close(); +?> diff --git a/export.php b/export.php new file mode 100755 index 0000000..7df3960 --- /dev/null +++ b/export.php @@ -0,0 +1,26 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +// FIXME +// Do we really need this? +// It is easier to export from web interface. +// If needed it may be easily adjusted from download.php +echo "<Result>0</Result>"; +exit(); +?> diff --git a/getpositions.php b/getpositions.php new file mode 100755 index 0000000..2f22aa0 --- /dev/null +++ b/getpositions.php @@ -0,0 +1,87 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +require_once("auth.php"); + +$userid = ((isset($_REQUEST["userid"]) && is_numeric($_REQUEST["userid"])) ? $_REQUEST["userid"] : 0); +$trackid = ((isset($_REQUEST["trackid"]) && is_numeric($_REQUEST["trackid"])) ? $_REQUEST["trackid"] : 0); + +function haversine_distance($lat1, $lon1, $lat2, $lon2) { + $lat1 = deg2rad($lat1); + $lon1 = deg2rad($lon1); + $lat2 = deg2rad($lat2); + $lon2 = deg2rad($lon2); + $latD = $lat2 - $lat1; + $lonD = $lon2 - $lon1; + $angle = 2*asin(sqrt(pow(sin($latD/2),2)+cos($lat1)*cos($lat2)*pow(sin($lonD/2),2))); + return $angle * 6371000; +} + +if ($userid) { + if ($trackid) { + // get all track data + $query = $mysqli->prepare("SELECT positions.ID,Latitude,Longitude,Altitude,Speed,Angle,DateOccurred,username,trips.Name,trips.ID FROM positions LEFT JOIN users ON (positions.FK_Users_ID=users.ID) LEFT JOIN trips ON (positions.FK_Trips_ID=trips.ID) WHERE positions.FK_Users_ID=? AND positions.FK_Trips_ID=? ORDER BY positions.DateOccurred"); + $query->bind_param('ii', $userid, $trackid); + } + else { + // get data only for latest point + $query = $mysqli->prepare("SELECT positions.ID,Latitude,Longitude,Altitude,Speed,Angle,DateOccurred,username,trips.Name,trips.ID FROM positions LEFT JOIN users ON (positions.FK_Users_ID=users.ID) LEFT JOIN trips ON (positions.FK_Trips_ID=trips.ID) WHERE positions.FK_Users_ID=? ORDER BY positions.DateOccurred DESC LIMIT 1"); + $query->bind_param('i', $userid); + } + $query->execute(); + $query->bind_result($positionid,$latitude,$longitude,$altitude,$speed,$angle,$dateoccured,$username,$trackname,$trackid); + + header("Content-type: text/xml"); + $xml = new XMLWriter(); + $xml->openURI("php://output"); + $xml->startDocument("1.0"); + $xml->setIndent(true); + $xml->startElement('root'); + + while ($query->fetch()) { + $xml->startElement("position"); + $xml->writeAttribute("id", $positionid); + $xml->writeElement("latitude", $latitude); + $xml->writeElement("longitude", $longitude); + $xml->writeElement("altitude", ($altitude)?round($altitude):$altitude); + $xml->writeElement("speed", $speed); + $xml->writeElement("angle", $angle); + $xml->writeElement("dateoccured", $dateoccured); + $xml->writeElement("username", $username); + $xml->writeElement("trackid", $trackid); + $xml->writeElement("trackname", $trackname); + $distance = (isset($prev_latitude))?haversine_distance($prev_latitude,$prev_longitude,$latitude,$longitude):0; + $prev_latitude = $latitude; + $prev_longitude = $longitude; + $xml->writeElement("distance", round($distance)); + $seconds = (isset($prev_dateoccured))?(strtotime($dateoccured)-strtotime($prev_dateoccured)):0; + $prev_dateoccured = $dateoccured; + $xml->writeElement("seconds", $seconds); + $xml->endElement(); + } + + $xml->endElement(); + $xml->endDocument(); + $xml->flush(); + + $query->free_result(); +} + +$mysqli->close(); +?> diff --git a/gettrips.php b/gettrips.php new file mode 100755 index 0000000..6883d08 --- /dev/null +++ b/gettrips.php @@ -0,0 +1,52 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +require_once("auth.php"); + +$userid = ((isset($_REQUEST["userid"]) && is_numeric($_REQUEST["userid"])) ? $_REQUEST["userid"] : 0); + +if ($userid) { + $query = $mysqli->prepare("SELECT ID,Name FROM trips WHERE FK_Users_ID=? ORDER BY ID DESC"); + $query->bind_param('i', $userid); + $query->execute(); + $query->bind_result($trackid,$trackname); + + header("Content-type: text/xml"); + $xml = new XMLWriter(); + $xml->openURI("php://output"); + $xml->startDocument("1.0"); + $xml->setIndent(true); + $xml->startElement('root'); + + while ($query->fetch()) { + $xml->startElement("trip"); + $xml->writeElement("trackid", $trackid); + $xml->writeElement("trackname", $trackname); + $xml->endElement(); + } + + $xml->endElement(); + $xml->endDocument(); + $xml->flush(); + + $query->free_result(); +} + +$mysqli->close(); +?> diff --git a/index.php b/index.php new file mode 100755 index 0000000..c50a06d --- /dev/null +++ b/index.php @@ -0,0 +1,186 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +require_once("auth.php"); + +if ($auth) { + // get username + $query = "SELECT username FROM users WHERE ID='$auth' LIMIT 1"; + $result = $mysqli->query($query); + $row = $result->fetch_assoc(); + $user = $row["username"]; + + // users + $user_form = '<u>'.$lang_user.'</u><br />'.$user.' (<a href="logout.php">'.$lang_logout.'</a>)'; +} +else { + // free access + // prepare user select form + $user_form = ' + <u>'.$lang_user.'</u><br /> + <form> + <select name="user" onchange="selectUser(this)"> + <option value=\"0\">'.$lang_suser.'</option>'; + $query = "SELECT ID,username FROM users ORDER BY username"; + $result = $mysqli->query($query); + while ($row = $result->fetch_assoc()) { + $user_form .= sprintf("<option value=\"%s\">%s</option>\n", $row["ID"], $row["username"]); + } +$user_form .= ' +</select> +</form> +'; +} + + +// prepare track select form +$track_form = ' +<u>'.$lang_track.'</u><br /> +<form> +<select name="track" onchange="selectTrack(this)">'; +$query = "SELECT * FROM trips WHERE FK_Users_ID='$auth' ORDER BY ID DESC"; +$result = $mysqli->query($query); +$trackid = ""; +while ($row = $result->fetch_assoc()) { + if ($trackid == "") { $trackid = $row["ID"]; } // get first row + $track_form .= sprintf("<option value=\"%s\">%s</option>\n", $row["ID"], $row["Name"]); +} +$track_form .= ' +</select> +<input id="latest" type="checkbox" onchange="toggleLatest();"> '.$lang_latest.'<br /> +</form> +'; + +print +'<!DOCTYPE html> +<html> + <head> + <title>'.$lang_title.'</title> + <meta http-equiv="Content-type" content="text/html;charset=UTF-8" /> + <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> + <link rel="stylesheet" type="text/css" href="main.css"> + <script> + var interval = '.$interval.'; + var userid = '.(($auth)?$auth:-1).'; + var trackid = '.(($trackid)?$trackid:-1).'; + var lang_user = "'.$lang_user.'"; + var lang_time = "'.$lang_time.'"; + var lang_speed = "'.$lang_speed.'"; + var lang_altitude = "'.$lang_altitude.'"; + var lang_ttime = "'.$lang_ttime.'"; + var lang_aspeed = "'.$lang_aspeed.'"; + var lang_tdistance = "'.$lang_tdistance.'"; + var lang_point = "'.$lang_point.'"; + var lang_of = "'.$lang_of.'"; + var lang_summary = "'.$lang_summary.'"; + var lang_latest = "'.$lang_latest.'"; + var lang_track = "'.$lang_track.'"; + var lang_newinterval = "'.$lang_newinterval.'"; + var units = "'.$units.'"; + </script> + <script type="text/javascript" src="main.js"> + </script> +'; +if ($mapapi == "gmaps") { + print +' <script type="text/javascript" + src="https://maps.googleapis.com/maps/api/js?'.(isset($gkey)?'key='.$gkey.'&':'').'sensor=false"> + </script> + <script type="text/javascript"> + var map; + var polies = new Array(); + var markers = new Array(); + var popups = new Array(); + google.maps.visualRefresh = true; + var polyOptions = { + strokeColor: \'#FF0000\', + strokeOpacity: 1.0, + strokeWeight: 2 + } + var mapOptions = { + center: new google.maps.LatLng(52.23, 21.01), + zoom: 8, + mapTypeId: google.maps.MapTypeId.ROADMAP, + scaleControl: true + }; + function init() { + map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); + } + </script> +'; +} +else { + print +' <script type="text/javascript" + src="http://openlayers.org/api/OpenLayers.js"> + </script> + <script> + function init() { + map = new OpenLayers.Map("map-canvas"); + map.addLayer(new OpenLayers.Layer.OSM()); + var fromProjection = new OpenLayers.Projection("EPSG:4326"); // Transform from WGS 1984 + var toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection + var position = new OpenLayers.LonLat(21.01,52.23).transform(fromProjection, toProjection); + var zoom = 8; + map.setCenter(position, zoom); + } + </script> +'; +} +print ' + <script type="text/javascript" src="https://www.google.com/jsapi"></script> + <script type="text/javascript"> + google.load("visualization", "1", {packages:["corechart"]}); + </script> + + </head> + <body onload="init();loadTrack(userid,trackid,1);"> + <div id="menu"> + <div id="menu-content"> + <div id="user"> + '.$user_form.' + </div> + <div id="trip"> + '.$track_form.' + <input id="latest" type="checkbox" onchange="autoReload();"> '.$lang_autoreload.' (<a href="javascript:void(0);" onclick="setTime()"><span id="auto">'.$interval.'</span></a> s)<br /> + <a href="javascript:void(0);" onclick="loadTrack(userid,trackid,0)">'.$lang_reload.'</a><br /> + </div> + <div id="summary"></div> + <div id="other"> + <a href="javascript:void(0);" onclick="toggleChart();">'.$lang_chart.'</a><br /> + </div> + <div id="export"> + <u>'.$lang_download.'</u><br /> + <a href="javascript:void(0);" onclick="load(\'kml\',userid,trackid)">kml</a><br /> + <a href="javascript:void(0);" onclick="load(\'gpx\',userid,trackid)">gpx</a><br /> + </div> + </div> + <div id="footer">phpTrackme '.$version.'</div> + </div> + <div id="main"> + <div id="map-canvas"></div> + <div id="bottom"> + <div id="chart"></div> + <div id="close"><a href="javascript:void(0);" onclick="toggleChart(0);">'.$lang_close.'</a></div> + </div> + </div> + </body> +</html>'; +$mysqli->close(); +?> diff --git a/lang.php b/lang.php new file mode 100755 index 0000000..bd508c9 --- /dev/null +++ b/lang.php @@ -0,0 +1,82 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +switch($lang) { + default: + case "en": + $lang_title = "fabiszewski.net • geolocation"; + $lang_private = "You need login and password to access this page."; + $lang_authfail = "Wrong username or password"; + $lang_user = "User"; + $lang_track = "Track"; + $lang_latest = "latest position"; + $lang_autoreload = "autoreload"; + $lang_reload = "Reload now"; + $lang_download = "Download data"; + $lang_chart = "Altitudes chart"; + $lang_close = "close"; + $lang_time = "Time"; + $lang_speed = "Speed"; + $lang_altitude = "Altitude"; + $lang_ttime = "Total time"; + $lang_aspeed = "Average speed"; + $lang_tdistance = "Total dist."; + $lang_point = "Point"; //Point x of y + $lang_of = "of"; + $lang_summary = "Trip summary"; + $lang_suser = "select user"; + $lang_logout = "log out"; + $lang_login = "Log in"; + $lang_username = "Username"; + $lang_password = "Password"; + $lang_language = "Language"; + $lang_newinterval = "Enter new interval value (seconds)"; + break; + + case "pl": + $lang_title = "fabiszewski.net • geolocation"; + $lang_private = "Aby się zalogować musisz podać login i hasło"; + $lang_authfail = "błędny login lub hasło"; + $lang_user = "Użytkownik"; + $lang_track = "Trasa"; + $lang_latest = "ostatnia pozycja"; + $lang_autoreload = "odświeżaj"; + $lang_reload = "Odśwież teraz"; + $lang_download = "Pobierz dane"; + $lang_chart = "Wykres przewyższeń"; + $lang_close = "zamknij"; + $lang_time = "Czas"; + $lang_speed = "Prędkość"; + $lang_altitude = "Wysokość"; + $lang_ttime = "Czas podróży"; + $lang_aspeed = "Średnia prędkość"; + $lang_tdistance = "Odległość"; + $lang_suser = "wybierz login"; + $lang_point = "Punkt"; + $lang_of = "z"; + $lang_summary = "Podsumowanie"; + $lang_logout = "wyloguj"; + $lang_login = "zaloguj"; + $lang_username = "Login"; + $lang_password = "Hasło"; + $lang_language = "Język"; + $lang_newinterval = "Podaj częstotliwość odświeżania (w sekundach)"; + break; +} +?> diff --git a/logout.php b/logout.php new file mode 100755 index 0000000..7a9f6c2 --- /dev/null +++ b/logout.php @@ -0,0 +1,30 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +session_name('trackme'); +session_start(); +$_SESSION = NULL; +if (isset($_COOKIE[session_name('trackme')])) { + setcookie(session_name('trackme'),'',time()-42000,'/'); +} +session_destroy(); +@$ssl = ($_SERVER['HTTPS'] == "" ? "http" : "https"); +$url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/index.php"); +header("Location: $ssl://$url"); +?> diff --git a/main.css b/main.css new file mode 100755 index 0000000..747b837 --- /dev/null +++ b/main.css @@ -0,0 +1,152 @@ +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +html { + height: 100%; +} +body { + height: 100%; + margin: 0; + padding: 0; + background-color: #666; +} +a { + color: #bce; + text-decoration: none; +} +:link, :visited { + color: #bce; +} +select { + width: 150px; + /*font-size: 0.6em;*/ + font-weight: normal; + padding-top: 0.2em; +} +input { + width: 150px; + text-align: center; + border: 1px solid black; +} +input[type = "submit"] { + background-color: black; + color: white; + border: 1px solid white; +} +input[type = "checkbox"] { + width: auto; +} +#main { + height: 100%; + margin-right: 165px; +} +#map-canvas { + height: 100%; +} +#menu { + font-family: Verdana, sans-serif; + font-size: 0.6em; + font-weight: bold; + color: white; + float: right; + width: 165px; + height: 100%; + background-color: #666; +} +#menu-content { + padding: 10px; +} +#footer { + position: fixed; + bottom:0; + padding: 10px; + background-color: #666; + color: lightgray; +} +#user, #trip, #summary, #export, #other { + padding-bottom: 10px; +} +#login { + font-family: Verdana, sans-serif; + position: relative; + top: 10%; + background-color: #444; + width: 30%; + min-width: 200px; + margin: auto; + padding: 30px; + font-size: 0.8em; + text-align: center; + color: white; +} +#title { + font-size: 1.3em; + padding-bottom: 0.5em; + padding-top: 0.6em; +} +#subtitle { + padding-bottom: 2em; +} +#error { + padding-top: 1.2em; + color: yellow; +} +#popup { + width:350px; + height:150px; +} +#pheader { + font-weight: bolder; + padding-bottom: 5px; + border-bottom: 1px solid gray; +} +#pleft,#pright { + float:left; + padding-top: 5px; +} +#pleft { + padding-right: 20px; +} +#pfooter { + clear: both; + font-size: smaller; + padding-top: 20px; +} +#bottom { + display: none; +} +#chart { + position: fixed; + bottom: 0; left:0; right: 0; + height: 200px; + margin-right: 165px; + background-color: white; + opacity: 0.8; +} +#close { + position: absolute; + bottom: 175px; + right: 175px; + z-index: 100; + font-family: Verdana, sans-serif; + font-size: 0.8em; +} + +#close a, #close:link, #close:visited { + color: #5070af; +} @@ -0,0 +1,412 @@ +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +// google maps +function displayTrack(xml,update) { + altitudes.length = 0; + var totalMeters = 0; + var totalSeconds = 0; + // init polyline + var poly = new google.maps.Polyline(polyOptions); + poly.setMap(map); + var path = poly.getPath(); + var latlngbounds = new google.maps.LatLngBounds( ); + var positions = xml.getElementsByTagName('position'); + var posLen = positions.length; + for (var i=0; i<posLen; i++) { + var p = parsePosition(positions[i]); + totalMeters += p.distance; + totalSeconds += p.seconds; + p['totalMeters'] = totalMeters; + p['totalSeconds'] = totalSeconds; + p['coordinates'] = new google.maps.LatLng(p.latitude,p.longitude); + // set marker + setMarker(p,i,posLen); + // update polyline + path.push(p.coordinates); + latlngbounds.extend(p.coordinates); + // save altitudes for chart + altitudes[i] = p.altitude; + } + if (update) { + map.fitBounds(latlngbounds); + if (i==1) { + // only one point, zoom out + zListener = + google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) { + if (this.getZoom()){ + this.setZoom(15); + } + }); + setTimeout(function(){google.maps.event.removeListener(zListener)}, 2000); + } + } + latestTime = p.dateoccured; + polies.push(poly); + + updateSummary(p.dateoccured,totalMeters,totalSeconds); + if (p.tid!=trackid) { + trackid=p.tid; + setTrack(trackid); + } + if (document.getElementById('bottom').style.display=='block') { + // update altitudes chart + chart.clearChart(); + displayChart(); + } +} + +function clearMap(){ + if (polies){ + for (var i=0; i<polies.length; i++){ + polies[i].setMap(null); + } + } + if (markers){ + for (var i=0; i<markers.length; i++){ + google.maps.event.removeListener(popups[i].listener); + popups[i].setMap(null); + markers[i].setMap(null); + } + } + markers.length = 0; + polies.length = 0; + popups.lentgth = 0; +} + +var popup; +function setMarker(p,i,posLen) { + // marker + var marker = new google.maps.Marker( { + map: map, + position: p.coordinates, + title: p.dateoccured + }); + if (latest==1) { marker.setIcon('http://maps.google.com/mapfiles/dd-end.png') } + else if (i==0) { marker.setIcon('http://maps.google.com/mapfiles/marker_greenA.png') } + else if (i==posLen-1) { marker.setIcon('http://maps.google.com/mapfiles/markerB.png') } + else { marker.setIcon('http://labs.google.com/ridefinder/images/mm_20_gray.png') } + // popup + var content = '<div id="popup">'+ + '<div id="pheader">'+lang_user+': '+p.username.toUpperCase()+'<br />'+lang_track+': '+p.trackname.toUpperCase()+ + '</div>'+ + '<div id="pbody">'+ + '<div id="pleft"><b>'+lang_time+':</b> '+p.dateoccured+'<br />'+ + ((p.speed != null)?'<b>'+lang_speed+':</b> '+(p.speed.toKmH()*factor_kmh)+' '+unit_kmh+'<br />':'')+ + ((p.altitude != null)?'<b>'+lang_altitude+':</b> '+(p.altitude*factor_m).toFixed()+' '+unit_m+'<br />':'')+'</div>'+ + ((latest==0)? + ('<div id="pright"><b>'+lang_ttime+':</b> '+p.totalSeconds.toHMS()+'<br />'+ + '<b>'+lang_aspeed+':</b> '+((p.totalSeconds>0)?((p.totalMeters/p.totalSeconds).toKmH()*factor_kmh).toFixed():0)+' '+unit_kmh+'<br />'+ + '<b>'+lang_tdistance+':</b> '+(p.totalMeters.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+'</div>'):'')+ + '<div id="pfooter">'+lang_point+' '+(i+1)+' '+lang_of+' '+(posLen)+'</div>'+ + '</div></div>'; + popup = new google.maps.InfoWindow(); + popup.listener = google.maps.event.addListener(marker, 'click', (function(marker,content) { + return function() { + popup.setContent(content); + popup.open(map, marker); + if (document.getElementById('bottom').style.display=='block') { + chart.setSelection([{row:i,column:null}]); + } + } + })(marker,content)); + markers.push(marker); + popups.push(popup); +} + + + +// openstreetmaps +// TODO + + +// general stuff +if (units=='imperial') { + factor_kmh = 0.62; //to mph + unit_kmh = 'mph'; + factor_m = 3.28; // to feet + unit_m = 'ft'; + factor_km = 0.62; // to miles + unit_km = 'mi'; +} +else { + factor_kmh = 1; + unit_kmh = 'km/h'; + factor_m = 1; + unit_m = 'm'; + factor_km = 1; + unit_km = 'km'; +} +var latest = 0; +var latestTime = 0; +var live = 0; +var chart; +var altitudes = new Array(); +var altTimeout; +function displayChart() { + if (chart) { google.visualization.events.removeAllListeners(chart); } + var data = new google.visualization.DataTable(); + data.addColumn('number', 'id'); + data.addColumn('number', 'altitude'); + var altLen = altitudes.length; + for (var i=0; i<altLen; i++) { + data.addRow([(i+1),Math.round((altitudes[i]*factor_m))]); + } + + var options = { + title: lang_altitude+' ('+unit_m+')', + hAxis: { textPosition: 'none' }, + legend: { position: 'none' } + }; + + chart = new google.visualization.LineChart(document.getElementById('chart')); + chart.draw(data, options); + + google.visualization.events.addListener(chart, 'select', function() { + if (popup) {popup.close(); clearTimeout(altTimeout);} + var selection = chart.getSelection()[0]; + if (selection) { + var id = selection.row; + var contentString = '<div style="width:40px; height:20px;padding:10px">'+Math.round(altitudes[id]*factor_m)+' '+unit_m+'</div>'; + popup = new google.maps.InfoWindow({ + content: contentString + }); + popup.open(map,markers[id]); + altTimeout = setTimeout(function() { if (popup) {popup.close();} },2000); + } + }); +} + +function toggleChart(i) { + var altLen = altitudes.length; + if (altLen<=1) { return; } + var e = document.getElementById('bottom'); + if (arguments.length < 1) { + if (e.style.display == 'block') { i = 0 } + else { i = 1; } + } + if (i==0) { + chart.clearChart(); + e.style.display = 'none'; + } + else { + e.style.display = 'block'; + displayChart(); + } +} + +function getXHR() { + var xmlhttp = null; + if (window.XMLHttpRequest) { + xmlhttp=new XMLHttpRequest(); + } + else { + xmlhttp=new ActiveXObject('Microsoft.XMLHTTP'); + } + return xmlhttp; +} + +function loadTrack(userid,trackid,update) { + if (latest==1) { trackid=0; } + var xhr = getXHR(); + xhr.onreadystatechange = function() { + if (xhr.readyState==4 && xhr.status==200) { + var xml = xhr.responseXML; + var positions = xml.getElementsByTagName('position'); + if (positions.length>0) { + clearMap(); + displayTrack(xml,update); + } + xhr = null; + } + } + xhr.open('GET','getpositions.php?trackid='+trackid+'&userid='+userid,true); + xhr.send(); +} + +function parsePosition(p) { + // read data + var latitude = getNode(p,'latitude'); + var longitude = getNode(p,'longitude'); + var altitude = getNode(p,'altitude'); // may be null + if (altitude != null) { altitude = parseInt(altitude); } + var speed = getNode(p,'speed'); // may be null + if (speed != null) { speed = parseInt(speed); } + var angle = getNode(p,'angle'); // may be null + if (angle != null) { angle = parseInt(angle); } + var username = getNode(p,'username'); + var trackname = getNode(p,'trackname'); + var tid = getNode(p,'trackid'); + var dateoccured = getNode(p,'dateoccured'); + var distance = parseInt(getNode(p,'distance')); + var seconds = parseInt(getNode(p,'seconds')); + return { + 'latitude': latitude, + 'longitude': longitude, + 'altitude': altitude, + 'speed': speed, + 'angle': angle, + 'username': username, + 'trackname': trackname, + 'tid': tid, + 'dateoccured': dateoccured, + 'distance': distance, + 'seconds': seconds + }; +} + +function load(type,userid,trackid) { + var url = 'download.php?type='+type+'&userid='+userid+'&trackid='+trackid; + window.location.assign(url); +} + +function updateSummary(l,d,s) { + var t = document.getElementById('summary'); + if (latest==0){ + t.innerHTML = '<u>'+lang_summary+'</u><br />'+ + lang_tdistance+': '+(d.toKm()*factor_km).toFixed(2)+' '+unit_km+'<br />'+ + lang_ttime+': '+s.toHMS(); + } + else { + t.innerHTML = '<u>'+lang_latest+':</u><br />'+l; + } +} + +function getNode(p,name) { + return ((p.getElementsByTagName(name)[0].childNodes[0]) ? p.getElementsByTagName(name)[0].childNodes[0].nodeValue : null); +} + + +// seconds to (d) H:M:S +Number.prototype.toHMS = function(){ + var s = this; + var d = Math.floor(s / 86400); + var h = Math.floor((s % 86400) / 3600); + var m = Math.floor(((s % 86400) % 3600) / 60); + s = ((s % 86400) % 3600) % 60; + + return ((d>0)?(d + ' d '):'') + (('00'+h).slice(-2)) + ':' + (('00'+m).slice(-2)) + ':' + (('00'+s).slice(-2)) + ''; +} +// meters to km +Number.prototype.toKm = function() { + return Math.round(this/10)/100; +} +// m/s to km/h +Number.prototype.toKmH = function() { + return Math.round(this*3600/10)/100; +} + +// negate value +function toggleLatest() { + if (latest==0) { + latest = 1; + loadTrack(userid,0,1); + } + else { + latest = 0; + loadTrack(userid,trackid,1); + } +} + +function setTrack(t) { + document.getElementsByName('track')[0].value = t; +} + +function selectTrack(f) { + trackid=f.options[f.selectedIndex].value; + document.getElementById('latest').checked = false; + if (latest==1) { toggleLatest(); } + loadTrack(userid,trackid,1); +} + +function selectUser(f) { + userid=f.options[f.selectedIndex].value; + if (f.options[0].disabled==false) { + f.options[0].disabled = true; + } + document.getElementById('latest').checked = false; + if (latest==1) { toggleLatest(); } + getTrips(userid); +} + +function getTrips(userid) { + var xhr = getXHR(); + xhr.onreadystatechange = function() { + if (xhr.readyState==4 && xhr.status==200) { + var xml = xhr.responseXML; + var trips = xml.getElementsByTagName('trip'); + if (trips.length>0) { + fillOptions(xml); + } + xhr = null; + } + } + xhr.open('GET','gettrips.php?userid='+userid,true); + xhr.send(); +} + +function fillOptions(xml) { + var trackSelect = document.getElementsByName('track')[0]; + clearOptions(trackSelect); + var trips = xml.getElementsByTagName('trip'); + var trpLen = trips.length; + for (var i=0; i<trpLen; i++) { + var trackid = getNode(trips[i],'trackid'); + var trackname = getNode(trips[i],'trackname'); + var option = document.createElement("option"); + option.value = trackid; + option.innerHTML = trackname; + trackSelect.appendChild(option); + } + var defaultTrack = getNode(trips[0],'trackid'); + loadTrack(userid,defaultTrack,1); +} + +function clearOptions(el){ + if (el.options) { + while (el.options.length) { + el.remove(0); + } + } +} + +var auto; +function autoReload() { + if (live==0) { + live = 1; + auto = setInterval(function() { loadTrack(userid,trackid,0); },interval*1000); + } + else { + live = 0; + clearInterval(auto); + } +} + +function setTime() { + var i = parseInt(prompt(lang_newinterval)); + if (!isNaN(i) && i!=interval) { + interval = i; + document.getElementById('auto').innerHTML = interval; + // if live tracking on, reload with new interval + if (live==1) { + live = 0; + clearInterval(auto); + autoReload(); + } + } +} diff --git a/requests.php b/requests.php new file mode 100755 index 0000000..38a0168 --- /dev/null +++ b/requests.php @@ -0,0 +1,268 @@ +<?php +/* phpTrackme + * + * Copyright(C) 2013 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +// TrackMe API +// http://forum.xda-developers.com/showpost.php?p=3250539&postcount=2 + +require_once("config.php"); +$user = (isset($_REQUEST['u']) ? $_REQUEST['u'] : ""); +$pass = (isset($_REQUEST['p']) ? md5($salt.$_REQUEST['p']) : ""); +$requireddb = (isset($_REQUEST['db']) ? $_REQUEST['db'] : 0); +$tripname = (isset($_REQUEST['tn']) ? $_REQUEST['tn'] : ""); +$action = (isset($_REQUEST['a']) ? $_REQUEST['a'] : ""); + +// FIXME what is it for? +if ($requireddb<8) { + //Result:5 Incompatible database. + quit(5); +} + +$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $dbname); +if ($mysqli->connect_errno) { + //Result:4 Unable to connect database. + quit(4); +} + +if ((!$user) || (!$pass)){ + //Result:3 User or password not specified. + quit(3); +} + +$query = $mysqli->prepare("SELECT ID,username,password FROM users WHERE username=? LIMIT 1"); +$query->bind_param('s', $user); +$query->execute(); +$query->store_result(); +$query->bind_result($userid, $rec_user, $rec_pass); +$query->fetch(); +$num = $query->num_rows; +$query->free_result(); +$query->close(); +if ($num) { + if (($user==$rec_user) && ($pass!=$rec_pass)) { + //Result:1 User correct, invalid password. + quit(1); + } +} +else { + if ($allow_registration) { + // User unknown, let's create it + $query = $mysqli->prepare("INSERT INTO users (username,password) VALUES (?,?)"); + $query->bind_param('ss', $user, $pass); + $query->execute(); + $userid = $mysqli->insert_id; + $query->close(); + if (!$userid) { + //Result:2 User did not exist but after being created couldn't be found. + // Or rather something went wrong while updating database + quit(2); + } + } + else { + // User unknown, we don't allow autoregistration + // Let's use this one: + //Result:1 User correct, invalid password. + quit(1); + } +} + +switch($action) { + // action: noop + case "noop": + // test + quit(0); + break; + + // action: deletetrip + case "deletetrip": + if ($tripname) { + $sql = "DELETE FROM positions LEFT JOIN trips ON positions.FK_Trips_ID=trips.ID " + ."WHERE positions.FK_Users_ID=? AND trips.Name=?"; + $query = $mysqli->prepare($sql); + if ($query) { + $query->bind_param('is', $userid, $tripname); + $query->execute(); + $query->close(); + } + $sql = "DELETE FROM trips WHERE FK_Users_ID=? AND Name=?"; + $query = $mysqli->prepare($sql); + $query->bind_param('is', $userid, $tripname); + $query->execute(); + $rows = $mysqli->affected_rows; + $query->close(); + if ($rows) { + quit(0); + } + else { + //Result:7 Trip not found + quit(7); + } + } + else { + //Result:6 Trip not specified. + quit(6); + } + break; + + // action: addtrip + case "addtrip": + if ($tripname) { + $sql = "INSERT INTO trips (FK_Users_ID,Name) VALUES (?,?)"; + $query = $mysqli->prepare($sql); + $query->bind_param('is', $userid, $tripname); + $query->execute(); + $query->close(); + } + else { + //Result:6 Trip not specified. + quit(6); + } + break; + + // action: gettriplist + case "gettriplist": + $sql = "SELECT a1.Name,(SELECT MIN(a2.DateOccurred) FROM positions a2 " + ."WHERE a2.FK_Trips_ID=a1.ID) AS startdate " + ."FROM trips a1 WHERE a1.FK_Users_ID=? ORDER BY Name"; + $query = $mysqli->prepare($sql); + $query->bind_param('i', $userid); + $query->execute(); + $query->store_result(); + $query->bind_result($tripname,$startdate); + $num = $query->num_rows; + $triplist = array(); + if ($num) { + while ($query->fetch()) { + $triplist[] = $tripname."|".$startdate; + } + } + $query->free_result(); + $query->close(); + $param = implode("\n",$triplist); + quit(0,$param); + break; + + // action: upload + case "upload": + $lat = isset($_REQUEST["lat"]) ? $_REQUEST["lat"] : NULL; + $long = isset($_REQUEST["long"]) ? $_REQUEST["long"] : NULL; + $dateoccurred = isset($_REQUEST["do"]) ? $_REQUEST["do"] : NULL; + $altitude = isset($_REQUEST["alt"]) ? $_REQUEST["alt"] : NULL; + $angle = isset($_REQUEST["ang"]) ? $_REQUEST["ang"] : NULL; + $speed = isset($_REQUEST["sp"]) ? $_REQUEST["sp"] : NULL; + $iconname = isset($_REQUEST["iconname"]) ? $_REQUEST["iconname"] : NULL; + $comments = isset($_REQUEST["comments"]) ? $_REQUEST["comments"] : NULL; + $imageurl = isset($_REQUEST["imageurl"]) ? $_REQUEST["imageurl"] : NULL; + $cellid = isset($_REQUEST["cid"]) ? $_REQUEST["cid"] : NULL; + $signalstrength = isset($_REQUEST["ss"]) ? $_REQUEST["ss"] : NULL; + $signalstrengthmax = isset($_REQUEST["ssmax"]) ? $_REQUEST["ssmax"] : NULL; + $signalstrengthmin = isset($_REQUEST["ssmin"]) ? $_REQUEST["ssmin"] : NULL; + $batterystatus = isset($_REQUEST["bs"]) ? $_REQUEST["bs"] : NULL; + $uploadss = isset($_REQUEST["upss"]) ? $_REQUEST["upss"] : NULL; // FIXME is it needed? + $iconid = NULL; + if ($iconname) { + $sql = "SELECT ID FROM icons WHERE Name=? LIMIT 1"; + $query = $mysqli->prepare($sql); + $query->bind_param('s', $iconname); + $query->execute(); + $query->store_result(); + $query->bind_result($id); + $query->fetch(); + $num = $query->num_rows; + $query->free_result(); + $query->close(); + if ($num) { + $iconid = $id; + } + } + $tripid = NULL; // FIXME: not sure what trips with null id are + if ($tripname) { + // get tripid + $query = $mysqli->prepare("SELECT ID FROM trips WHERE FK_Users_ID=? AND Name=? LIMIT 1"); + $query->bind_param('is', $userid, $tripname); + $query->execute(); + $query->store_result(); + $query->bind_result($tripid); + $query->fetch(); + $num = $query->num_rows; + $query->free_result(); + $query->close(); + if (!$num) { + // create trip + $query = $mysqli->prepare("INSERT INTO trips (FK_Users_ID,Name) VALUES (?,?)"); + $query->bind_param('is', $userid, $tripname); + $query->execute(); + $tripid = $mysqli->insert_id; + $query->close(); + if (!$tripid) { + //Result:6 Trip didn't exist and system was unable to create it. + quit(6); + } + } + } + $sql = "INSERT INTO positions " + ."(FK_Users_ID,FK_Trips_ID,Latitude,Longitude,DateOccurred,FK_Icons_ID," + ."Speed,Altitude,Comments,ImageURL,Angle,SignalStrength,SignalStrengthMax," + ."SignalStrengthMin,BatteryStatus) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; + $query = $mysqli->prepare($sql); + $query->bind_param('iiddsiddssdiiii', + $userid,$tripid,$lat,$long,$dateoccurred,$iconid, + $speed,$altitude,$comments,$imageurl,$angle,$signalstrength,$signalstrengthmax, + $signalstrengthmin,$batterystatus); + $query->execute(); + $query->close(); + if ($mysqli->errno) { + //Result:7|SQLERROR Insert statement failed. + quit(7,$mysqli->error); + } + //FIXME Are cellids used in Android client? + $upcellext = isset($_REQUEST["upcellext"]) ? $_REQUEST["upcellext"] : NULL; + if ($upcellext==1 && $cellid) { + $sql = "INSERT INTO cellids (CellID,Latitude,Longitude,SignalStrength,SignalStrengthMax,SignalStrengthMin) " + ."VALUES (?,?,?,?,?,?)"; + $query = $mysqli->prepare($sql); + $query->bind_param('sddiii',$cellid,$lat,$long,$signalstrength,$signalstrengthmax,$signalstrengthmin); + $query->execute(); + $query->close(); + if ($mysqli->errno) { + //Result:7|SQLERROR Insert statement failed. + quit(7,$mysqli->error); + } + } + quit(0); + break; + + // action: geticonlist + // action: renametrip + // action: findclosestbuddy + // action: delete + // action: sendemail + // action: updateimageurl + // action: findclosestpositionbytime + // action: findclosestpositionbyposition + // action: gettripinfo + // action: gettriphighlights +} + +function quit($errno,$param=""){ + print "Result:".$errno.(($param)?"|$param":""); + exit(); +} + +$mysqli->close(); +?> diff --git a/trackme.sql b/trackme.sql new file mode 100755 index 0000000..0559277 --- /dev/null +++ b/trackme.sql @@ -0,0 +1,128 @@ +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; +CREATE DATABASE IF NOT EXISTS `trackme` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci; +USE `trackme`; + +CREATE TABLE IF NOT EXISTS `cellids` ( + `ID` int(11) NOT NULL auto_increment, + `CellID` varchar(255) NOT NULL, + `Latitude` double NOT NULL, + `Longitude` double NOT NULL, + `DateAdded` timestamp NOT NULL default CURRENT_TIMESTAMP, + `SignalStrength` int(11) default NULL, + `SignalStrengthMax` int(11) default NULL, + `SignalStrengthMin` int(11) default NULL, + PRIMARY KEY (`ID`), + KEY `Index_CellID` (`CellID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `icons` ( + `ID` int(11) NOT NULL auto_increment, + `Name` varchar(255) NOT NULL, + `URL` varchar(512) NOT NULL, + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `positions` ( + `ID` int(11) NOT NULL auto_increment, + `FK_Users_ID` int(11) NOT NULL, + `FK_Trips_ID` int(11) default NULL, + `FK_Icons_ID` int(11) default NULL, + `Latitude` double NOT NULL, + `Longitude` double NOT NULL, + `Altitude` double default '0', + `Speed` double default '0', + `Angle` double default NULL, + `DateAdded` timestamp NOT NULL default CURRENT_TIMESTAMP, + `DateOccurred` timestamp NULL default '0000-00-00 00:00:00', + `Comments` varchar(255) default NULL, + `ImageURL` varchar(255) default NULL, + `SignalStrength` int(11) default NULL, + `SignalStrengthMax` int(11) default NULL, + `SignalStrengthMin` int(11) default NULL, + `BatteryStatus` tinyint(4) default NULL, + PRIMARY KEY (`ID`), + KEY `Index_FK_Trips_ID` (`FK_Trips_ID`), + KEY `Index_FK_Users_ID` (`FK_Users_ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `trips` ( + `ID` int(11) NOT NULL auto_increment, + `FK_Users_ID` int(11) NOT NULL, + `Name` varchar(255) NOT NULL, + `Comments` varchar(1024) default NULL, + PRIMARY KEY (`ID`), + UNIQUE KEY `Index_FK_Users_ID_Name` (`FK_Users_ID`,`Name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `users` ( + `ID` int(11) NOT NULL auto_increment, + `username` varchar(15) NOT NULL, + `password` varchar(50) NOT NULL default '', + PRIMARY KEY (`ID`), + UNIQUE KEY `Index_username` (`username`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `icons` VALUES (1, 'Snack', 'http://maps.google.com/mapfiles/ms/micons/snack_bar.png'); +INSERT INTO `icons` VALUES (2, 'Hiking', 'http://maps.google.com/mapfiles/ms/micons/hiker.png'); +INSERT INTO `icons` VALUES (3, 'Lodging', 'http://maps.google.com/mapfiles/ms/micons/lodging.png'); +INSERT INTO `icons` VALUES (4, 'Restaurant', 'http://maps.google.com/mapfiles/ms/micons/restaurant.png'); +INSERT INTO `icons` VALUES (5, 'POI', 'http://maps.google.com/mapfiles/ms/micons/POI.png'); +INSERT INTO `icons` VALUES (6, 'Arts', 'http://maps.google.com/mapfiles/ms/micons/arts.png'); +INSERT INTO `icons` VALUES (7, 'Bar', 'http://maps.google.com/mapfiles/ms/micons/bar.png'); +INSERT INTO `icons` VALUES (8, 'Blue-dot', 'http://maps.google.com/mapfiles/ms/micons/blue-dot.png'); +INSERT INTO `icons` VALUES (9, 'Bus', 'http://maps.google.com/mapfiles/ms/micons/bus.png'); +INSERT INTO `icons` VALUES (10, 'Taxi', 'http://maps.google.com/mapfiles/ms/micons/cabs.png'); +INSERT INTO `icons` VALUES (11, 'Camera', 'http://maps.google.com/mapfiles/ms/micons/camera.png'); +INSERT INTO `icons` VALUES (12, 'Camping', 'http://maps.google.com/mapfiles/ms/micons/campground.png'); +INSERT INTO `icons` VALUES (13, 'Caution', 'http://maps.google.com/mapfiles/ms/micons/caution.png'); +INSERT INTO `icons` VALUES (14, 'Coffee House', 'http://maps.google.com/mapfiles/ms/micons/coffeehouse.png'); +INSERT INTO `icons` VALUES (15, 'Store', 'http://maps.google.com/mapfiles/ms/micons/convienancestore.png'); +INSERT INTO `icons` VALUES (16, 'Cycling', 'http://maps.google.com/mapfiles/ms/micons/cycling.png'); +INSERT INTO `icons` VALUES (17, 'Dollar', 'http://maps.google.com/mapfiles/ms/micons/dollar.png'); +INSERT INTO `icons` VALUES (18, 'Drinking water', 'http://maps.google.com/mapfiles/ms/micons/drinking_water.png'); +INSERT INTO `icons` VALUES (19, 'Electronics', 'http://maps.google.com/mapfiles/ms/micons/electronics.png'); +INSERT INTO `icons` VALUES (20, 'Falling Rocks', 'http://maps.google.com/mapfiles/ms/micons/fallingrocks.png'); +INSERT INTO `icons` VALUES (21, 'Ferry', 'http://maps.google.com/mapfiles/ms/micons/ferry.png'); +INSERT INTO `icons` VALUES (22, 'Fire Dept.', 'http://maps.google.com/mapfiles/ms/micons/firedept.png'); +INSERT INTO `icons` VALUES (23, 'Fishing', 'http://maps.google.com/mapfiles/ms/micons/fishing.png'); +INSERT INTO `icons` VALUES (24, 'Flag', 'http://maps.google.com/mapfiles/ms/micons/flag.png'); +INSERT INTO `icons` VALUES (25, 'Gas', 'http://maps.google.com/mapfiles/ms/micons/gas.png'); +INSERT INTO `icons` VALUES (26, 'Grocery Store', 'http://maps.google.com/mapfiles/ms/micons/grocerystore.png'); +INSERT INTO `icons` VALUES (27, 'Helicopter', 'http://maps.google.com/mapfiles/ms/micons/helicopter.png'); +INSERT INTO `icons` VALUES (28, 'Horseback riding', 'http://maps.google.com/mapfiles/ms/micons/horsebackriding.png'); +INSERT INTO `icons` VALUES (29, 'Hospital', 'http://maps.google.com/mapfiles/ms/micons/hospitals.png'); +INSERT INTO `icons` VALUES (30, 'Hot springs', 'http://maps.google.com/mapfiles/ms/micons/hotsprings.png'); +INSERT INTO `icons` VALUES (31, 'Info', 'http://maps.google.com/mapfiles/ms/micons/info.png'); +INSERT INTO `icons` VALUES (32, 'Info 2', 'http://maps.google.com/mapfiles/ms/micons/info_circle.png'); +INSERT INTO `icons` VALUES (33, 'Man', 'http://maps.google.com/mapfiles/ms/micons/man.png'); +INSERT INTO `icons` VALUES (34, 'Marina', 'http://maps.google.com/mapfiles/ms/micons/marina.png'); +INSERT INTO `icons` VALUES (35, 'Mechanic', 'http://maps.google.com/mapfiles/ms/micons/mechanic.png'); +INSERT INTO `icons` VALUES (36, 'Motorcycling', 'http://maps.google.com/mapfiles/ms/micons/motorcycling.png'); +INSERT INTO `icons` VALUES (37, 'Parking', 'http://maps.google.com/mapfiles/ms/micons/parkinglot.png'); +INSERT INTO `icons` VALUES (38, 'Partly Cloudy', 'http://maps.google.com/mapfiles/ms/micons/partly_cloudy.png'); +INSERT INTO `icons` VALUES (39, 'Phone', 'http://maps.google.com/mapfiles/ms/micons/phone.png'); +INSERT INTO `icons` VALUES (40, 'Picnic', 'http://maps.google.com/mapfiles/ms/micons/picnic.png'); +INSERT INTO `icons` VALUES (41, 'Plane', 'http://maps.google.com/mapfiles/ms/micons/plane.png'); +INSERT INTO `icons` VALUES (42, 'Police', 'http://maps.google.com/mapfiles/ms/micons/police.png'); +INSERT INTO `icons` VALUES (43, 'Post Office', 'http://maps.google.com/mapfiles/ms/micons/postoffice-us.png'); +INSERT INTO `icons` VALUES (44, 'Question mark', 'http://maps.google.com/mapfiles/ms/micons/question.png'); +INSERT INTO `icons` VALUES (45, 'Rail', 'http://maps.google.com/mapfiles/ms/micons/rail.png'); +INSERT INTO `icons` VALUES (46, 'Rainy', 'http://maps.google.com/mapfiles/ms/micons/rainy.png'); +INSERT INTO `icons` VALUES (47, 'Ranger Station', 'http://maps.google.com/mapfiles/ms/micons/rangerstation.png'); +INSERT INTO `icons` VALUES (48, 'Recycle', 'http://maps.google.com/mapfiles/ms/micons/recycle.png'); +INSERT INTO `icons` VALUES (49, 'Snow', 'http://maps.google.com/mapfiles/ms/micons/snowflake_simple.png'); +INSERT INTO `icons` VALUES (50, 'Sport', 'http://maps.google.com/mapfiles/ms/micons/sportvenue.png'); +INSERT INTO `icons` VALUES (51, 'Subway', 'http://maps.google.com/mapfiles/ms/micons/subway.png'); +INSERT INTO `icons` VALUES (52, 'Sunny', 'http://maps.google.com/mapfiles/ms/micons/sunny.png'); +INSERT INTO `icons` VALUES (53, 'Swimming', 'http://maps.google.com/mapfiles/ms/micons/swimming.png'); +INSERT INTO `icons` VALUES (54, 'Toilets', 'http://maps.google.com/mapfiles/ms/micons/toilets.png'); +INSERT INTO `icons` VALUES (55, 'Trail', 'http://maps.google.com/mapfiles/ms/micons/trail.png'); +INSERT INTO `icons` VALUES (56, 'Tree', 'http://maps.google.com/mapfiles/ms/micons/tree.png'); +INSERT INTO `icons` VALUES (57, 'Truck', 'http://maps.google.com/mapfiles/ms/micons/truck.png'); +INSERT INTO `icons` VALUES (58, 'Volcano', 'http://maps.google.com/mapfiles/ms/micons/volcano.png'); +INSERT INTO `icons` VALUES (59, 'Water', 'http://maps.google.com/mapfiles/ms/micons/water.png'); +INSERT INTO `icons` VALUES (60, 'Waterfalls', 'http://maps.google.com/mapfiles/ms/micons/waterfalls.png'); +INSERT INTO `icons` VALUES (61, 'Wheel Chair', 'http://maps.google.com/mapfiles/ms/micons/wheel_chair_accessible.png'); +INSERT INTO `icons` VALUES (62, 'Woman', 'http://maps.google.com/mapfiles/ms/micons/woman.png'); +INSERT INTO `icons` VALUES (63, 'Monster gate', 'http://img.gamespot.com/gamespot/shared/user/emblem_e3monster_s.jpg'); |