<?php
/* ----------------------------------------------------------------- */
/*                                                                   */
/*  v1.0  5.1.2017   Stephan Weber                                   */
/*    kml_gpx(kml, gpx)                                              */
/*       kml(kmz) in gpx umwandeln <trk> in gpx file schreiben       */
/*       optional: &wpt=n (oder irgendwas anderes hinterm '=':       */
/*          auch alle <wpt> ins gpx tun                              */
/*    wie kann man daraus eine mediawiki extension machen?           */
/* http://www.zdnet.de/39151524/eigene-erweiterungen-fuer-mediawiki-schreiben/ */
/*                                                                   */
/*  v1.1  3.5.2017 reine server-version                              */
/*                                                                   */
/*    aufruf
         http://php.hutmachergass.de/kml_gpx.php?url=http://radreise-wiki.de/images/Radweit_Münster_-_Bremen_(retour).kmz
*/
/*                                                                   */
/*    v1.2 8.5.2017 lösung: s.u. curl                                */
/*                                                                   */
/*    v1.3 10.5.2017 kommentare bereinigt                            */
/*       gpx-files wurden nicht gelöscht, deswegen $gpxworkfile      */
/*                                                                   */
/*    v1.4 11.5.2017 liste der downloads führen                      */
/*                                                                   */
/*    v1.5 12.5.2017 track name gefunden; sack und asche!            */
/*                                                                   */
/*    v1.6 13.5.2017 rechenzeit ins log schreiben                    */
/*       unlink($kmzfn); aus dem if-block raus, da gehörts nicht hin */
/*                                                                   */
/*    v1.7 15.5.2017 regex mit utf-8 chars                           */
/*       sein gelassen, macht nicht viel sinn                        */
/*                                                                   */
/*    v1.8 19.5.2017 tempfilename unabhängig vom echten namen wählen */
/*       logging der dauer des curl-aufrufs                          */
/*                                                                   */
/*    v1.9 20.5.2017 auf temp files ganz verzichten?                 */
/*       zumindest auf gpxtmp                                        */
/*       logging mit ';'                                             */
/*                                                                   */
/*    v2.0 9.6.2017 function hitliste()                              */
/*       logfile lesen, hitliste machen und als html table ausgeben  */
/*                                                                   */
/* ----------------------------------------------------------------- */
 
/* ----------------------------------------------------------------- */
/*
kml to gpx converter, von hier, via stackoverflow:
http://thydzik.com/convert-from-google-kml-to-gps-exchange-format-gpx/
code-entwurf s. erste version dieses teils.
*/
/* ----------------------------------------------------------------- */
 
/* ----------------------------------------------------------------- */
/* ----- functions -----                                             */
/* ----------------------------------------------------------------- */
 
/* ----------------------------------------------------------------- */
/* helpers                                                           */
/* ----------------------------------------------------------------- */
function traceprint($tracebool, $printstring)
{
if ($tracebool) echo $printstring;
}  // traceprint()
 
/* ----------------------------------------------------------------- */
function traceprintr($tracebool, $arrname, $printarray)
{
if ($tracebool)
   {
   echo "\ntraceprint $arrname\n";
   print_r($printarray);
   }
}  // traceprintr()
 
/* ----------------------------------------------------------------- */
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
 
/* ----------------------------------------------------------------- */
function utcdate()
{
   return gmdate("Y-m-d\Th:i:s\Z");
}
 
 
/* ----------------------------------------------------------------- */
/* kml to gpx converter, von hier, via stackoverflow                 */
/* http://thydzik.com/convert-from-google-kml-to-gps-exchange-format-gpx/ */
/* ----------------------------------------------------------------- */
function kml_gpx($kmldoc, &$gpxdoc, &$arOpts)
{
if (null !== $kmldoc)
   {
   $dom_kml = new DOMDocument();
   $dom_kml->loadXML($kmldoc);
 
   $dom_gpx = new DOMDocument('1.0', 'UTF-8');
   $dom_gpx->formatOutput = true;
 
   //root node
   $gpx = $dom_gpx->createElement('gpx');
   $gpx = $dom_gpx->appendChild($gpx);
 
   $gpx_version = $dom_gpx->createAttribute('version');
   $gpx->appendChild($gpx_version);
   $gpx_version_text = $dom_gpx->createTextNode('1.0');
   $gpx_version->appendChild($gpx_version_text);
 
   $gpx_creator = $dom_gpx->createAttribute('creator');
   $gpx->appendChild($gpx_creator);
   $gpx_creator_text = $dom_gpx->createTextNode('http://thydzik.com');
   $gpx_creator->appendChild($gpx_creator_text);
 
   $gpx_xmlns_xsi = $dom_gpx->createAttribute('xmlns:xsi');
   $gpx->appendChild($gpx_xmlns_xsi);
   $gpx_xmlns_xsi_text = $dom_gpx->createTextNode('http://www.w3.org/2001/XMLSchema-instance');
   $gpx_xmlns_xsi->appendChild($gpx_xmlns_xsi_text);
 
   $gpx_xmlns = $dom_gpx->createAttribute('xmlns');
   $gpx->appendChild($gpx_xmlns);
   $gpx_xmlns_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0');
   $gpx_xmlns->appendChild($gpx_xmlns_text);
 
   $gpx_xsi_schemaLocation = $dom_gpx->createAttribute('xsi:schemaLocation');
   $gpx->appendChild($gpx_xsi_schemaLocation);
   $gpx_xsi_schemaLocation_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd');
   $gpx_xsi_schemaLocation->appendChild($gpx_xsi_schemaLocation_text);
 
   $gpx_time = $dom_gpx->createElement('time');
   $gpx_time = $gpx->appendChild($gpx_time);
   $gpx_time_text = $dom_gpx->createTextNode(utcdate());
   $gpx_time->appendChild($gpx_time_text);
 
 
   // placemarks
   $names = array();
   foreach ($dom_kml->getElementsByTagName('Placemark') as $placemark)
      {
      //name
      foreach ($placemark->getElementsByTagName('name') as $name)
         {
         $name  = $name->nodeValue;
         //check if the key exists
         if (array_key_exists($name, $names))
            {
            //increment the value
            ++$names[$name];
            $name = $name." ({$names[$name]})";
            }
         else
            {
            $names[$name] = 0;
            }
         }
 
      //description
      $trkdesc = '';
      foreach ($placemark->getElementsByTagName('description') as $description)
         {
         $description  = $description->nodeValue;
         $trkdesc = $description;
         }
 
      // 12.5.2017 der track name steht in <Document><name>Saar</name> bzw <Document><Placemark><name>Saar GPS-Track</name>
      $trkname = '';
      foreach ($placemark->getElementsByTagName('name') as $trackname)
         {
         $trackname = $trackname->nodeValue;
         $trkname = $trackname;
         }
 
      if ($arOpts['wpt'])
         {
         foreach ($placemark->getElementsByTagName('Point') as $point)
            {
            foreach ($point->getElementsByTagName('coordinates') as $coordinates)
               {
               //add the marker
               $coordinate = $coordinates->nodeValue;
               $coordinate = str_replace(" ", "", $coordinate);   // trim white space - sinnlos, wenn da \t und \n drin stehen!
               $coordinate = trim($coordinate);
               $latlng = explode(",", $coordinate);
 
               if (($lat = $latlng[1]) && ($lng = $latlng[0]))
                  {
                  $gpx_wpt = $dom_gpx->createElement('wpt');
                  $gpx_wpt = $gpx->appendChild($gpx_wpt);
 
                  $gpx_wpt_lat = $dom_gpx->createAttribute('lat');
                  $gpx_wpt->appendChild($gpx_wpt_lat);
                  $gpx_wpt_lat_text = $dom_gpx->createTextNode($lat);
                  $gpx_wpt_lat->appendChild($gpx_wpt_lat_text);
 
                  $gpx_wpt_lon = $dom_gpx->createAttribute('lon');
                  $gpx_wpt->appendChild($gpx_wpt_lon);
                  $gpx_wpt_lon_text = $dom_gpx->createTextNode($lng);
                  $gpx_wpt_lon->appendChild($gpx_wpt_lon_text);
 
                  // und wo bleibt die <ele>?? also:
                  if ($ele = $latlng[2])
                     {
                     $gpx_ele = $dom_gpx->createElement('ele');
                     $gpx_ele = $gpx_wpt->appendChild($gpx_ele);
                     $gpx_ele_text = $dom_gpx->createTextNode($ele);
                     $gpx_ele->appendChild($gpx_ele_text);
                     }
 
                  $gpx_name = $dom_gpx->createElement('name');
                  $gpx_name = $gpx_wpt->appendChild($gpx_name);
                  $gpx_name_text = $dom_gpx->createTextNode($name);
                  $gpx_name->appendChild($gpx_name_text);
 
                  $gpx_desc = $dom_gpx->createElement('desc');
                  $gpx_desc = $gpx_wpt->appendChild($gpx_desc);
                  $gpx_desc_text = $dom_gpx->createTextNode($description);
                  $gpx_desc->appendChild($gpx_desc_text);
 
                  $gpx_sym = $dom_gpx->createElement('sym');
                  $gpx_sym = $gpx_wpt->appendChild($gpx_sym);
                  $gpx_sym_text = $dom_gpx->createTextNode('Waypoint');
                  $gpx_sym->appendChild($gpx_sym_text);
               }
            }
         }  // if aropts wpt
      }
 
      foreach ($placemark->getElementsByTagName('LineString') as $lineString)
         {
         foreach ($lineString->getElementsByTagName('coordinates') as $coordinates)
            {
            //add the new track
            $gpx_trk = $dom_gpx->createElement('trk');
            $gpx_trk = $gpx->appendChild($gpx_trk);
 
            $gpx_name = $dom_gpx->createElement('name');
            $gpx_name = $gpx_trk->appendChild($gpx_name);
            $gpx_name_text = $dom_gpx->createTextNode($trkname);
            // $gpx_name_text = $dom_gpx->createTextNode('track name');
            $gpx_name->appendChild($gpx_name_text);
 
            // description aus der placemark description
            $gpx_desc = $dom_gpx->createElement('desc');
            $gpx_desc = $gpx_trk->appendChild($gpx_desc);
            $gpx_desc_text = $dom_gpx->createTextNode($trkdesc);
            $gpx_desc->appendChild($gpx_desc_text);
 
            $gpx_trkseg = $dom_gpx->createElement('trkseg');
            $gpx_trkseg = $gpx_trk->appendChild($gpx_trkseg);
 
            $coordinates = $coordinates->nodeValue;
            //split the coords by new line
            $coordinates = preg_split("/[\s\r\n]+/", $coordinates);
 
            foreach ($coordinates as $coordinate)
               {
               if ('' != $coordinate)
                  $latlng = explode(",", $coordinate);
               else {
                  continue;
               }
 
               if (($lat = $latlng[1]) && ($lng = $latlng[0]))
                  {
                  $gpx_trkpt = $dom_gpx->createElement('trkpt');
                  $gpx_trkpt = $gpx_trkseg->appendChild($gpx_trkpt);
 
                  $gpx_trkpt_lat = $dom_gpx->createAttribute('lat');
                  $gpx_trkpt->appendChild($gpx_trkpt_lat);
                  $gpx_trkpt_lat_text = $dom_gpx->createTextNode($lat);
                  $gpx_trkpt_lat->appendChild($gpx_trkpt_lat_text);
 
                  $gpx_trkpt_lon = $dom_gpx->createAttribute('lon');
                  $gpx_trkpt->appendChild($gpx_trkpt_lon);
                  $gpx_trkpt_lon_text = $dom_gpx->createTextNode($lng);
                  $gpx_trkpt_lon->appendChild($gpx_trkpt_lon_text);
 
                  /* makes absolutely no sense to write the same time for all trkpt
                  $gpx_time = $dom_gpx->createElement('time');
                  $gpx_time = $gpx_trkpt->appendChild($gpx_time);
                  $gpx_time_text = $dom_gpx->createTextNode(utcdate());
                  $gpx_time->appendChild($gpx_time_text);
                  */
 
                  // und wo bleibt die <ele>?? also:
                  if ($ele = $latlng[2])
                     {
                     $gpx_ele = $dom_gpx->createElement('ele');
                     $gpx_ele = $gpx_trkpt->appendChild($gpx_ele);
                     $gpx_ele_text = $dom_gpx->createTextNode($ele);
                     $gpx_ele->appendChild($gpx_ele_text);
                     }
                  }
               }
            }
         }
      }
   $gpxdoc = $dom_gpx->saveXML();
   }
 
}  // kml_gpx()
 
 
/* ----------------------------------------------------------------- */
/*
timestamp;computingtime;trackname
20170608230743;0.250;Ostseeküstenradweg
*/
/* ----------------------------------------------------------------- */
function hitliste($logfn, &$arOpts)
{
if ((null !== $logfn) && ('' != $logfn))
   $arlog = file($logfn, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
else die("no valid logfile");
 
$total = count($arlog);    // wird auch in der headline gebraucht
 
// überschrift
$arlogline = explode(';', $arlog[0]);
$datum = $arlogline[0];
$adatum = substr($datum, 6, 2).'.'.substr($datum, 4, 2).'.'.substr($datum, 0, 4);
 
$arlogline = explode(';', $arlog[$total - 1]);
$datum = $arlogline[0];
$edatum = substr($datum, 6, 2).'.'.substr($datum, 4, 2).'.'.substr($datum, 0, 4);
 
$arlogtracks = array();
 
foreach ($arlog as $logline)
   {
   list(, , $trackname) = explode(';', $logline);
   $arlogtracks[] = $trackname;
   }  // foreach
 
unset($arlog); // no more needed
 
sort($arlogtracks, SORT_STRING); // array sortierter tracknamen
 
$artrackcount = array();   // array(trackname, anzahl)
$trkn = $arlogtracks[0];   // start value
$trkcnt = 0;
foreach ($arlogtracks as $trackname)
   {
   if (0 == strcmp($trkn, $trackname))
      $trkcnt++;
   else
      {
      // anzahl + trackname in array schreiben
      $artrackcount[] = $trkcnt.';'.$trkn;
      $trkcnt = 1;
      }
   $trkn = $trackname;
   }  // foreach
 
unset($arlogtracks);
 
rsort($artrackcount, SORT_NUMERIC);
 
$htmltitle = 'Radreise-Wiki Rangliste Trackdownloads';
$headline = 'Rangliste von '.$adatum.' bis '.$edatum.' - '.count($artrackcount).' Radrouten, '.$total.' GPX-Downloads';
 
// das folgende irgendwohin als template legen !!!
$htmlhead = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
         <html><head><meta charset="UTF-8"><title>'.$htmltitle.'</title></head>';
 
$htmlbody = '<body><h3>'.$headline.'</h3>';
$htmltable = '<table border cellspacing=0 cellpadding=0><tr><th>Anzahl</th><th>Track</th></tr>';
foreach ($artrackcount as $hitline)
   {
   $items = explode(';', $hitline);
   $htmltable .= "\n".'<tr><td>'.$items[0].'</td><td>'.$items[1].'</td></tr>';
   }
 
$htmlbody .= $htmltable.'</table></body></html>';
 
print($htmlhead.$htmlbody);
 
}  // hitliste
 
 
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
/* --- main --- */
/* ----------------------------------------------------------------- */
/* ----------------------------------------------------------------- */
date_default_timezone_set('Europe/Paris');
 
$trace = 0; // wenn der höchste verwendete tracelevel 8 ist, dann
            // werden mit trace = 15 alle tracelevels angezeigt
            // 2: simple trace; 4: echo xml; 8: mysql; 128: input
 
$azeit = microtime_float();
 
if ($trace & 128)
   {
   echo "<br>POST:";
   print_r($_POST);
   echo "<br>SERVER QUERYSTRING: ";
   echo $_SERVER['QUERY_STRING'];
   echo "<br>SERVER SERVERNAME: ";
   echo $_SERVER['SERVER_NAME'];
   exit();
   }
 
$arOpts = array();
$arOpts['wpt'] = true;
$hitliste = false;
 
$kmzurl = '';
 
if ($_SERVER['QUERY_STRING'])
   {
   $querystr = $_SERVER['QUERY_STRING'];
 
   if ("" != $querystr)
      {
      /* check for ?parms */
      parse_str($querystr);
 
      if ($url) $kmzurl = $url;
 
      if ($wpt) $arOpts['wpt'] = false;
 
      if ($hits) $hitliste = true;
 
      }  /* args present */
   }  // $_SERVER['QUERY_STRING']
else
   die("aufruf: ?url=&lt;path-to-kmz&gt;; option [&wpt=n] für gpx ohne waypoints");
 
 
/* ----------------------------------------------------------------- */
$workdir = './work/';
$logfn = $workdir.'log.txt';
 
if ($hitliste)
   {
   hitliste($logfn, $arOpts);
   exit(0);
   }
 
$urlparts = pathinfo($kmzurl);
$filename = $urlparts['filename'];
$kmztmpfn = $workdir.$azeit.'.kmz';    // code injection prevention
 
// create a new cURL resource
$ch = curl_init();
 
// set URL and other appropriate options
curl_setopt($ch, CURLOPT_URL, $kmzurl);
//return the transfer as a string
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
 
// grab URL and pass it to $kmzcontents
$kmzcontents = curl_exec($ch);
$curlinfo = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// close cURL resource, and free up system resources
curl_close($ch);
 
// zeit für den curl-aufruf loggen
$fcurlzeit = microtime_float() - $azeit;
$scurlzeit = sprintf("%2.3f", $fcurlzeit);
 
if (0 != strcmp ('200', $curlinfo))
   die("could not open $kmzurl ($scurlzeit s)");
 
// write stuff to local temp file
if (false === file_put_contents($kmztmpfn, $kmzcontents))
   die("write error with $kmztmpfn");
 
unset($kmzcontents);    // delete buffer
 
$kmldoc = '';
$zip = new ZipArchive;
if (true === $zip->open($kmztmpfn))
   {
   // $zip->extractTo($dir);
   $fp = $zip->getStream('doc.kml');
   if (!$fp)
      {
      unlink($kmztmpfn);   // delete kmz file
      die("failed to get stream\n");
      }
 
   while (!feof($fp))
      $kmldoc .= fread($fp, 2);
 
   fclose($fp);
   $zip->close();
   }
 
unlink($kmztmpfn);   // delete kmz file
 
$gpxdoc ='';
kml_gpx($kmldoc, $gpxdoc, $arOpts);
 
header('Content-Disposition: attachment; filename='.$filename.'.gpx');
header('Content-type: text/xml');
 
print($gpxdoc);
 
 
$ezeit = microtime_float();
$rechenzeit = sprintf("%2.3f", $ezeit - $azeit);
if (1.0 < $fcurlzeit) $rechenzeit = $rechenzeit."($scurlzeit)";  // curl logging
 
// log
$logbuf = date("YmdHis").';'.$rechenzeit.';'.$filename."\n";
$logbuf = file_put_contents($logfn, $logbuf, FILE_APPEND);
unset($logbuf);
 
/* ----------------------------------------------------------------- */
?>