From 33b581b47af24594b06a1c20e33bf32521ed9dcf Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Tue, 9 May 2017 09:06:23 +0200 Subject: [PATCH] Add gpx import feature (closes #14) --- css/main.css | 2 +- index.php | 15 +++- js/main.js | 35 ++++++++- lang/de.php | 2 +- lang/en.php | 6 +- lang/es.php | 2 +- lang/fr.php | 2 +- lang/hu.php | 2 +- lang/it.php | 2 +- lang/pl.php | 5 +- utils/{download.php => export.php} | 4 +- utils/import.php | 109 +++++++++++++++++++++++++++++ 12 files changed, 170 insertions(+), 16 deletions(-) rename utils/{download.php => export.php} (98%) create mode 100755 utils/import.php diff --git a/css/main.css b/css/main.css index 001fb30..b2ca6b6 100755 --- a/css/main.css +++ b/css/main.css @@ -106,7 +106,7 @@ select { cursor: pointer; } -#user, #track, #summary, #export, #other, #units { +#user, #track, #summary, #export, #import, #other, #units { padding-bottom: 10px; } #summary span { diff --git a/index.php b/index.php index cb5aa18..b25c9b4 100755 --- a/index.php +++ b/index.php @@ -189,12 +189,21 @@
-
- kml - gpx +
+ kml + gpx
isValid): ?> +
+
+
+ + +
+ gpx +
+

isAdmin): ?> diff --git a/js/main.js b/js/main.js index fb2fc66..d703281 100755 --- a/js/main.js +++ b/js/main.js @@ -217,11 +217,42 @@ function getPopupHtml(p, i, count) { return popup; } -function load(type, userid, trackid) { - var url = 'utils/download.php?type=' + type + '&userid=' + userid + '&trackid=' + trackid; +function exportFile(type, userid, trackid) { + var url = 'utils/export.php?type=' + type + '&userid=' + userid + '&trackid=' + trackid; window.location.assign(url); } +function importFile(input){ + var xhr = getXHR(); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4 && xhr.status == 200) { + var xml = xhr.responseXML; + var message = ""; + if (xml) { + var root = xml.getElementsByTagName('root'); + if (root.length && getNode(root[0], 'error') == 0) { + trackId = getNode(root[0], 'trackid'); + getTracks(userid); + loadTrack(userid, trackId, 1); + return; + } + errorMsg = getNode(root[0], 'message'); + if (errorMsg) { message = errorMsg; } + } + alert(lang['actionfailure'] + '\n' + message); + xhr = null; + } + } + xhr.upload.onprogress = function(e) { + console.log(e.loaded, e.total) + } + xhr.upload.onload = function(e) { + console.log('file upload') + } + xhr.open("POST", "utils/import.php", true); + xhr.send(new FormData(input.parentElement)); +} + function updateSummary(l, d, s) { var t = document.getElementById('summary'); if (latest == 0) { diff --git a/lang/de.php b/lang/de.php index b160e73..56686a1 100644 --- a/lang/de.php +++ b/lang/de.php @@ -25,7 +25,7 @@ $lang["track"] = "Route"; $lang["latest"] = "letzte Position"; $lang["autoreload"] = "Autoneuladen"; $lang["reload"] = "Neuladen"; -$lang["download"] = "Download Daten"; +$lang["export"] = "Download Daten"; $lang["chart"] = "Höhentabelle"; $lang["close"] = "Schließen"; $lang["time"] = "Zeit"; diff --git a/lang/en.php b/lang/en.php index 9645d86..9bada49 100644 --- a/lang/en.php +++ b/lang/en.php @@ -54,7 +54,7 @@ $lang["track"] = "Track"; $lang["latest"] = "latest position"; $lang["autoreload"] = "autoreload"; $lang["reload"] = "Reload now"; -$lang["download"] = "Download data"; +$lang["export"] = "Export track"; $lang["chart"] = "Altitudes chart"; $lang["close"] = "close"; $lang["time"] = "Time"; @@ -114,5 +114,7 @@ $lang["passrules"][3] = "It should contain at least one lower case letter, one u $lang["owntrackswarn"] = "Your can only edit your own tracks"; $lang["gmauthfailure"] = "There may be problem with Google Maps API key on this page"; $lang["gmapilink"] = "You may find more information about API keys on this Google webpage"; - +$lang["import"] = "Import track"; +$lang["iparsefailure"] = "Parsing failed"; +$lang["idatafailure"] = "No track data in imported file"; ?> diff --git a/lang/es.php b/lang/es.php index 360b264..a1c8699 100644 --- a/lang/es.php +++ b/lang/es.php @@ -25,7 +25,7 @@ $lang["track"] = "Rastro"; $lang["latest"] = "última posición"; $lang["autoreload"] = "autorecarga"; $lang["reload"] = "Recargar ahora"; -$lang["download"] = "Descargar datos"; +$lang["export"] = "Descargar datos"; $lang["chart"] = "Gráfico de altitudes"; $lang["close"] = "cerrar"; $lang["time"] = "Hora"; diff --git a/lang/fr.php b/lang/fr.php index df97e60..9186f1c 100755 --- a/lang/fr.php +++ b/lang/fr.php @@ -25,7 +25,7 @@ $lang["track"] = "Piste"; $lang["latest"] = "dernière position"; $lang["autoreload"] = "rechargement automatique"; $lang["reload"] = "Recharger maintenant"; -$lang["download"] = "Télécharger les données"; +$lang["export"] = "Télécharger les données"; $lang["chart"] = "Courbes d'altitudes"; $lang["close"] = "fermer"; $lang["time"] = "Temps"; diff --git a/lang/hu.php b/lang/hu.php index 75ea964..159052b 100644 --- a/lang/hu.php +++ b/lang/hu.php @@ -25,7 +25,7 @@ $lang["track"] = "Útvonal"; $lang["latest"] = "Utolsó rögzített pont"; $lang["autoreload"] = "Automatikus frissítés"; $lang["reload"] = "Frissítés most"; -$lang["download"] = "Adatok letöltése"; +$lang["export"] = "Adatok letöltése"; $lang["chart"] = "Magasság diagramm"; $lang["close"] = "Bezár"; $lang["time"] = "Rögzítés ideje"; diff --git a/lang/it.php b/lang/it.php index f94b5d9..351f131 100644 --- a/lang/it.php +++ b/lang/it.php @@ -54,7 +54,7 @@ $lang["track"] = "Traccia"; $lang["latest"] = "ultima posizione"; $lang["autoreload"] = "auto-ricarica"; $lang["reload"] = "Ricarica ora"; -$lang["download"] = "Scarica dati"; +$lang["export"] = "Scarica dati"; $lang["chart"] = "Grafico altitudine"; $lang["close"] = "chiudi"; $lang["time"] = "Ora"; diff --git a/lang/pl.php b/lang/pl.php index b1817ac..adca967 100644 --- a/lang/pl.php +++ b/lang/pl.php @@ -49,7 +49,7 @@ $lang["track"] = "Trasa"; $lang["latest"] = "ostatnia pozycja"; $lang["autoreload"] = "odświeżaj"; $lang["reload"] = "Odśwież teraz"; -$lang["download"] = "Pobierz dane"; +$lang["export"] = "Eksportuj trasę"; $lang["chart"] = "Wykres przewyższeń"; $lang["close"] = "zamknij"; $lang["time"] = "Czas"; @@ -109,5 +109,8 @@ $lang["passrules"][3] = "Powinno ono zawierać przynajmniej jedną małą, jedn $lang["owntrackswarn"] = "Możesz edytować tylko swoje własne trasy"; $lang["gmauthfailure"] = "Prawdopodobnie na tej stronie występuje problem z kluczem API Google Maps"; $lang["gmapilink"] = "Więcej informacji o kluczach API znajdziesz pod tym linkiem"; +$lang["import"] = "Importuj trasę"; +$lang["iparsefailure"] = "Błąd parsowania pliku"; +$lang["idatafailure"] = "Brak trasy w importowanym pliku"; ?> diff --git a/utils/download.php b/utils/export.php similarity index 98% rename from utils/download.php rename to utils/export.php index 34e022f..374bb23 100755 --- a/utils/download.php +++ b/utils/export.php @@ -182,7 +182,7 @@ if ($trackId && $userId) { $xml->writeAttribute("version", "1.1"); $xml->startElement("metadata"); $xml->writeElement("name", $positionsArr[0]->trackName); - $xml->writeElement("time", str_replace(" ", "T", $positionsArr[0]->time)); + $xml->writeElement("time", gmdate("Y-m-d\TH:i:s\Z", strtotime($positionsArr[0]->time))); $xml->endElement(); $xml->startElement("trk"); $xml->writeElement("name", $positionsArr[0]->trackName); @@ -200,7 +200,7 @@ if ($trackId && $userId) { $xml->writeAttribute("lat", $position->latitude); $xml->writeAttribute("lon", $position->longitude); if (!is_null($position->altitude)) { $xml->writeElement("ele", $position->altitude); } - $xml->writeElement("time", str_replace(" ", "T", $position->time)); + $xml->writeElement("time", gmdate("Y-m-d\TH:i:s\Z", strtotime($position->time))); $xml->writeElement("name", ++$i); $xml->startElement("desc"); $description = diff --git a/utils/import.php b/utils/import.php new file mode 100755 index 0000000..9450dce --- /dev/null +++ b/utils/import.php @@ -0,0 +1,109 @@ +. + */ + +require_once(dirname(__DIR__) . "/auth.php"); // sets $user +require_once(ROOT_DIR . "/helpers/track.php"); +require_once(ROOT_DIR . "/helpers/position.php"); + +/** + * Exit with xml response + * @param boolean $isError Error if true + * @param string $errorMessage Optional error message + */ +function exitWithStatus($isError, $errorMessage = NULL, $trackId = NULL) { + header("Content-type: text/xml"); + $xml = new XMLWriter(); + $xml->openURI("php://output"); + $xml->startDocument("1.0"); + $xml->setIndent(true); + $xml->startElement('root'); + $xml->writeElement("error", (int) $isError); + if ($isError) { + $xml->writeElement("message", $errorMessage); + } else { + $xml->writeElement("trackid", $trackId); + } + $xml->endElement(); + $xml->endDocument(); + $xml->flush(); + exit; +} + +if (!$user->isValid) { + exitWithStatus(true, $lang["servererror"]); +} + +$sizeMax = 10 * 1024 * 1024; //FIXME: set to php limits +$gpxFile = NULL; +$gpxUpload = $_FILES["gpx"]; +if ($gpxUpload["error"] == UPLOAD_ERR_OK && $gpxUpload["size"] < $sizeMax) { + $gpxFile = $gpxUpload["tmp_name"]; + $gpxName = basename($gpxUpload["name"]); +} + +$gpx = false; +libxml_use_internal_errors(true); +if ($gpxFile && file_exists($gpxFile)) { + $gpx = simplexml_load_file($gpxFile); +} + +if ($gpx === false) { + $message = $lang["iparsefailure"]; + $parserMessages = []; + foreach(libxml_get_errors() as $parseError) { + $parserMessages[] = $parseError->message; + } + $parserMessage = implode(", ", $parserMessages); + if (!empty($parserMessage)) { + $message .= ": $parserMessage"; + } + if ($gpxUpload["error"] != UPLOAD_ERR_OK) { + $message .= " (" . $gpxUpload["error"] . ")"; + } + exitWithStatus(true, $message); +} +else if (empty($gpx->trk)) { + exitWithStatus(true, $lang["idatafailure"]); +} + +$trackName = empty($gpx->trk->name) ? $gpxName : $gpx->trk->name->__toString(); +$metaName = empty($gpx->metadata->name) ? NULL : $gpx->metadata->name->__toString(); +$track = new uTrack(); +$trackId = $track->add($user->id, $trackName, $metaName); +if ($trackId === false) { + exitWithStatus(true, $lang["servererror"]); + break; +} + +$position = new uPosition(); +foreach($gpx->trk->trkseg as $segment) { + foreach($segment->trkpt as $point) { + $ret = $position->add($user->id, $trackId, + strtotime($point->time), $point["lat"], $point["lon"], $point->ele, + NULL, NULL, NULL, "gps", NULL, NULL); + if ($ret === false) { + exitWithStatus(true, $lang["servererror"]); + } + } +} + +// return track id +exitWithStatus(false, NULL, $trackId); + +?> \ No newline at end of file