From c46486396c54145232a5a9e9811123aacb11c8b4 Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Sun, 9 Apr 2017 23:35:55 +0200 Subject: [PATCH] Update phpdoc, minor formatting --- adduser.php | 6 +- admin.js | 6 +- api_gmaps.js | 92 +++++----- api_openlayers.js | 135 ++++++++------- auth.php | 4 +- changepass.php | 16 +- client/index.php | 12 +- config.default.php | 2 +- download.php | 15 +- getpositions.php | 4 +- gettracks.php | 2 +- helpers/config.php | 97 ++++++----- helpers/db.php | 59 ++++--- helpers/position.php | 142 ++++++++++----- helpers/track.php | 34 +++- helpers/user.php | 62 ++++++- index.php | 4 +- lang.php | 4 +- lang/de.php | 2 +- lang/en.php | 2 +- lang/es.php | 2 +- lang/fr.php | 2 +- lang/hu.php | 2 +- lang/pl.php | 1 - logout.php | 5 +- main.css | 8 +- main.js | 260 +++++++++++++++------------- pass.js | 6 +- scripts/migrate_from_phptrackme.php | 8 +- 29 files changed, 599 insertions(+), 395 deletions(-) diff --git a/adduser.php b/adduser.php index d0df146..ab85eb3 100644 --- a/adduser.php +++ b/adduser.php @@ -16,10 +16,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); // sets $mysqli, $user - - /** + + /** * Exit with xml response * @param boolean $isError Error if true * @param string $errorMessage Optional error message diff --git a/admin.js b/admin.js index 0434915..8baf01c 100644 --- a/admin.js +++ b/admin.js @@ -40,12 +40,12 @@ function submitUser() { return; } var xhr = getXHR(); - xhr.onreadystatechange = function() { - if (xhr.readyState==4 && xhr.status==200) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4 && xhr.status == 200) { var xml = xhr.responseXML; var message = ""; if (xml) { - var root = xml.getElementsByTagName('root'); + var root = xml.getElementsByTagName('root'); if (root.length && getNode(root[0], 'error') == 0) { removeModal(); alert("User successfully added"); diff --git a/api_gmaps.js b/api_gmaps.js index aa895cb..a800b67 100755 --- a/api_gmaps.js +++ b/api_gmaps.js @@ -24,6 +24,7 @@ var popups = new Array(); var polyOptions; var mapOptions; var loadedAPI = 'gmaps'; + function init() { google.maps.visualRefresh = true; polyOptions = { @@ -32,7 +33,7 @@ function init() { strokeWeight: 2 } mapOptions = { - center: new google.maps.LatLng(init_latitude,init_longitude), + center: new google.maps.LatLng(init_latitude, init_longitude), zoom: 8, mapTypeId: google.maps.MapTypeId.ROADMAP, scaleControl: true @@ -40,7 +41,7 @@ function init() { map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions); } -function displayTrack(xml,update) { +function displayTrack(xml, update) { altitudes.length = 0; var totalMeters = 0; var totalSeconds = 0; @@ -48,18 +49,18 @@ function displayTrack(xml,update) { var poly = new google.maps.Polyline(polyOptions); poly.setMap(map); var path = poly.getPath(); - var latlngbounds = new google.maps.LatLngBounds( ); + var latlngbounds = new google.maps.LatLngBounds(); var positions = xml.getElementsByTagName('position'); var posLen = positions.length; - for (var i=0; i0) { - for (var j = map.popups.length-1; j>=0; j-- ) { - map.removePopup(map.popups[j]) - }; + var content = getPopupHtml(p, i, posLen); + marker.events.register("mousedown", marker, (function () { + return function () { + // remove popups + if (map.popups.length > 0) { + for (var j = map.popups.length - 1; j >= 0; j--) { + map.removePopup(map.popups[j]) + }; + } + // show popup + var popup = new OpenLayers.Popup.FramedCloud("popup_" + (i + 1), lonLat, null, content, icon, true); + map.addPopup(popup); + if (document.getElementById('bottom').style.display == 'block') { + chart.setSelection([{ row: i, column: null }]); + } } - // show popup - var popup = new OpenLayers.Popup.FramedCloud("popup_"+(i+1),lonLat,null,content,icon,true); - map.addPopup(popup); - if (document.getElementById('bottom').style.display=='block') { - chart.setSelection([{row:i,column:null}]); - } - } })()); } function addChartEvent(chart) { - google.visualization.events.addListener(chart, 'select', function() { + google.visualization.events.addListener(chart, 'select', function () { var selection = chart.getSelection()[0]; if (selection) { var id = selection.row; var marker = layerMarkers.markers[id]; var url = marker.icon.url; marker.setUrl('//www.openstreetmap.org/openlayers/img/marker-gold.png'); - altTimeout = setTimeout(function() { marker.setUrl(url); },2000); + altTimeout = setTimeout(function () { marker.setUrl(url); }, 2000); } }); } //20.597985430276808,52.15547181298076,21.363595171488573,52.33750879522563 function getBounds() { - var b = map.getExtent().transform(mercator,wgs84).toString(); - var bounds = b.split(',',4); + var b = map.getExtent().transform(mercator, wgs84).toString(); + var bounds = b.split(',', 4); var lon_sw = bounds[0]; var lat_sw = bounds[1]; var lon_ne = bounds[2]; var lat_ne = bounds[3]; - return [lon_sw,lat_sw,lon_ne,lat_ne]; + return [lon_sw, lat_sw, lon_ne, lat_ne]; } function zoomToBounds(b) { - var bounds = new OpenLayers.Bounds(b).transform(wgs84,mercator); + var bounds = new OpenLayers.Bounds(b).transform(wgs84, mercator); map.zoomToExtent(bounds); } diff --git a/auth.php b/auth.php index ae6f64a..7b69d6d 100755 --- a/auth.php +++ b/auth.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("helpers/config.php"); $config = new uConfig(); @@ -46,7 +46,7 @@ if (!$user->isValid && ($config::$require_authentication || defined('headless')) if (!$login){ // not authenticated and username not submited - // load form + // load form if (defined('headless')) { header('HTTP/1.1 401 Unauthorized', true, 401); } else { diff --git a/changepass.php b/changepass.php index 9702dfc..c20ef3e 100644 --- a/changepass.php +++ b/changepass.php @@ -16,13 +16,19 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); // sets $mysqli, $user - + + /** + * Exit with error message + * + * @param string $errorMessage Message + */ function exitWithError($errorMessage) { return exitWithStatus(true, $errorMessage); } - /** + + /** * Exit with xml response * @param boolean $isError Error if true * @param string $errorMessage Optional error message @@ -67,7 +73,7 @@ if ($passUser->setPass($hash) === false) { exitWithError("Server error"); } - + exitWithStatus(); - + ?> \ No newline at end of file diff --git a/client/index.php b/client/index.php index af43810..ce80a13 100644 --- a/client/index.php +++ b/client/index.php @@ -17,12 +17,18 @@ * along with this program; if not, see . */ +/** + * Set response error status and message + * + * @param array $response Respons + * @param string $message Message + */ function setError(&$response, $message) { - $response['error'] = true; + $response['error'] = true; $response['message'] = $message; } -define("headless", true); +define("headless", true); require_once("../auth.php"); // sets $mysqli, $user $action = isset($_REQUEST['action']) ? $_REQUEST['action'] : null; @@ -92,7 +98,7 @@ switch ($action) { $position = new uPosition(); $positionId = $position->add($user->id, $trackId, $time, $lat, $lon, $altitude, $speed, $bearing, $accuracy, $provider, $comment, $imageId); - + if ($positionId === false) { setError($response, "Server error"); } diff --git a/config.default.php b/config.default.php index de5a62d..3232cdf 100755 --- a/config.default.php +++ b/config.default.php @@ -17,7 +17,7 @@ * along with this program; if not, see . */ -// This is default configuration file. +// This is default configuration file. // Copy it to config.php and customize // default map drawing framework diff --git a/download.php b/download.php index a280d15..eca89dd 100755 --- a/download.php +++ b/download.php @@ -16,10 +16,17 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); // sets $mysqli, $user require_once("helpers/position.php"); +/** + * Add kml marker style element + * + * @param XMLWriter $xml Writer object + * @param string $name Color name + * @param string $url Url + */ function addStyle($xml, $name, $url) { $xml->startElement("Style"); $xml->writeAttribute("id", $name."Style"); @@ -32,6 +39,12 @@ function addStyle($xml, $name, $url) { $xml->endElement(); } +/** + * Convert seconds to [day], hour, minute, second string + * + * @param [type] $s Number of seconds + * @return string [d ]hhmmss + */ function toHMS($s) { $d = floor($s / 86400); $h = floor(($s % 86400) / 3600); diff --git a/getpositions.php b/getpositions.php index 1db157a..6ae2b2b 100755 --- a/getpositions.php +++ b/getpositions.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); // sets $mysqli, $user require_once("helpers/position.php"); @@ -34,7 +34,7 @@ if ($userId) { $position->getLast($userId); $positionsArr[] = $position; } - + header("Content-type: text/xml"); $xml = new XMLWriter(); $xml->openURI("php://output"); diff --git a/gettracks.php b/gettracks.php index fdbc7bc..e390914 100755 --- a/gettracks.php +++ b/gettracks.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); // sets $mysqli, $user require_once("helpers/track.php"); diff --git a/helpers/config.php b/helpers/config.php index 5ce8244..72b9306 100644 --- a/helpers/config.php +++ b/helpers/config.php @@ -17,7 +17,10 @@ * along with this program; if not, see . */ -class uConfig { + /** + * Handles config values + */ + class uConfig { // version number static $version = "0.2-beta"; @@ -77,50 +80,60 @@ class uConfig { private static $fileLoaded = false; public static $rootDir; + /** + * Constructor + */ public function __construct() { - self::$rootDir = dirname(__DIR__); - $this->setFromFile(); - $this->setFromCookies(); - } + self::$rootDir = dirname(__DIR__); + $this->setFromFile(); + $this->setFromCookies(); + } - private function setFromFile() { - $configFile = self::$rootDir . "/config.php"; - if (self::$fileLoaded || !file_exists($configFile)) { - return; - } - self::$fileLoaded = true; - include_once($configFile); + /** + * Read config values from "/config.php" file + */ + private function setFromFile() { + $configFile = self::$rootDir . "/config.php"; + if (self::$fileLoaded || !file_exists($configFile)) { + return; + } + self::$fileLoaded = true; + include_once($configFile); - if (isset($mapapi)) { self::$mapapi = $mapapi; } - if (isset($gkey)) { self::$gkey = $gkey; } - if (isset($layer_ocm)) { self::$layer_ocm = $layer_ocm; } - if (isset($layer_mq)) { self::$layer_mq = $layer_mq; } - if (isset($layer_osmapa)) { self::$layer_osmapa = $layer_osmapa; } - if (isset($layer_ump)) { self::$layer_ump = $layer_ump; } - if (isset($init_latitude)) { self::$init_latitude = $init_latitude; } - if (isset($init_longitude)) { self::$init_longitude = $init_longitude; } - if (isset($dbhost)) { self::$dbhost = $dbhost; } - if (isset($dbuser)) { self::$dbuser = $dbuser; } - if (isset($dbpass)) { self::$dbpass = $dbpass; } - if (isset($dbname)) { self::$dbname = $dbname; } - if (isset($require_authentication)) { self::$require_authentication = (bool) $require_authentication; } - if (isset($public_tracks)) { self::$public_tracks = (bool) $public_tracks; } - if (isset($admin_user)) { self::$admin_user = $admin_user; } - if (isset($interval)) { self::$interval = $interval; } - if (isset($lang)) { self::$lang = $lang; } - if (isset($units)) { self::$units = $units; } + if (isset($mapapi)) { self::$mapapi = $mapapi; } + if (isset($gkey)) { self::$gkey = $gkey; } + if (isset($layer_ocm)) { self::$layer_ocm = $layer_ocm; } + if (isset($layer_mq)) { self::$layer_mq = $layer_mq; } + if (isset($layer_osmapa)) { self::$layer_osmapa = $layer_osmapa; } + if (isset($layer_ump)) { self::$layer_ump = $layer_ump; } + if (isset($init_latitude)) { self::$init_latitude = $init_latitude; } + if (isset($init_longitude)) { self::$init_longitude = $init_longitude; } + if (isset($dbhost)) { self::$dbhost = $dbhost; } + if (isset($dbuser)) { self::$dbuser = $dbuser; } + if (isset($dbpass)) { self::$dbpass = $dbpass; } + if (isset($dbname)) { self::$dbname = $dbname; } + if (isset($require_authentication)) { self::$require_authentication = (bool) $require_authentication; } + if (isset($public_tracks)) { self::$public_tracks = (bool) $public_tracks; } + if (isset($admin_user)) { self::$admin_user = $admin_user; } + if (isset($interval)) { self::$interval = $interval; } + if (isset($lang)) { self::$lang = $lang; } + if (isset($units)) { self::$units = $units; } - if (!self::$require_authentication) { - // tracks must be public if we don't require authentication - self::$public_tracks = true; - } - } - private function setFromCookies() { - if (isset($_COOKIE["ulogger_api"])) { self::$mapapi = $_COOKIE["ulogger_api"]; } - if (isset($_COOKIE["ulogger_lang"])) { self::$lang = $_COOKIE["ulogger_lang"]; } - if (isset($_COOKIE["ulogger_units"])) { self::$units = $_COOKIE["ulogger_units"]; } - if (isset($_COOKIE["ulogger_interval"])) { self::$interval = $_COOKIE["ulogger_interval"]; } - } -} + if (!self::$require_authentication) { + // tracks must be public if we don't require authentication + self::$public_tracks = true; + } + } + + /** + * Read config values stored in cookies + */ + private function setFromCookies() { + if (isset($_COOKIE["ulogger_api"])) { self::$mapapi = $_COOKIE["ulogger_api"]; } + if (isset($_COOKIE["ulogger_lang"])) { self::$lang = $_COOKIE["ulogger_lang"]; } + if (isset($_COOKIE["ulogger_units"])) { self::$units = $_COOKIE["ulogger_units"]; } + if (isset($_COOKIE["ulogger_interval"])) { self::$interval = $_COOKIE["ulogger_interval"]; } + } + } ?> \ No newline at end of file diff --git a/helpers/db.php b/helpers/db.php index c6fdc46..7a5c805 100644 --- a/helpers/db.php +++ b/helpers/db.php @@ -17,31 +17,48 @@ * along with this program; if not, see . */ -require_once (__DIR__ . "/config.php"); -class uDb extends mysqli { - // singleton instance - protected static $instance; + require_once (__DIR__ . "/config.php"); - // private constuctor - private function __construct($host, $user, $pass, $name) { - parent::__construct($host, $user, $pass, $name); - if ($this->connect_error) { - if (defined('headless')) { - header("HTTP/1.1 503 Service Unavailable"); - exit; + /** + * mysqli wrapper + */ + class uDb extends mysqli { + /** + * Singleton instance + * + * @var mysqli Object instance + */ + protected static $instance; + + /** + * Private constuctor + * + * @param string $host + * @param string $user + * @param string $pass + * @param string $name + */ + private function __construct($host, $user, $pass, $name) { + parent::__construct($host, $user, $pass, $name); + if ($this->connect_error) { + if (defined('headless')) { + header("HTTP/1.1 503 Service Unavailable"); + exit; + } + die("Database connection error (" . $this->connect_errno . ")"); } - die("Database connection error (" . $this->connect_errno . ")"); + $this->set_charset('utf8'); } - $this->set_charset('utf8'); - } - // returns singleton instance - public static function getInstance() { - if (!self::$instance) { - $config = new uConfig(); - self::$instance = new self($config::$dbhost, $config::$dbuser, $config::$dbpass, $config::$dbname); + /** + * Returns singleton instance + */ + public static function getInstance() { + if (!self::$instance) { + $config = new uConfig(); + self::$instance = new self($config::$dbhost, $config::$dbuser, $config::$dbpass, $config::$dbname); + } + return self::$instance; } - return self::$instance; } -} ?> \ No newline at end of file diff --git a/helpers/position.php b/helpers/position.php index 51551d1..99cdd7b 100644 --- a/helpers/position.php +++ b/helpers/position.php @@ -17,9 +17,12 @@ * along with this program; if not, see . */ -require_once(__DIR__ . "/db.php"); + require_once(__DIR__ . "/db.php"); -class uPosition { + /** + * Positions handling + */ + class uPosition { public $id; public $time; public $userId; @@ -40,23 +43,44 @@ class uPosition { private static $db; + /** + * Constructor + * @param integer $positionId Position id + */ public function __construct($positionId = NULL) { self::$db = uDB::getInstance(); if (!empty($positionId)) { - $query = "SELECT p.id, p.time, p.user_id, p.track_id, - p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, - p.comment, p.image_id, u.login, t.name - FROM positions p - LEFT JOIN users u ON (p.user_id = u.id) - LEFT JOIN tracks t ON (p.track_id = t.id) + $query = "SELECT p.id, p.time, p.user_id, p.track_id, + p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, + p.comment, p.image_id, u.login, t.name + FROM positions p + LEFT JOIN users u ON (p.user_id = u.id) + LEFT JOIN tracks t ON (p.track_id = t.id) WHERE id = ? LIMIT 1"; $params = [ 'i', $positionId ]; $this->loadWithQuery($query, $params); } } + /** + * Add position + * + * @param int $userId + * @param int $trackId + * @param int $time Unix time stamp + * @param double $lat + * @param double $lon + * @param double $altitude + * @param double $speed + * @param double $bearing + * @param int $accuracy + * @param string $provider + * @param string $comment + * @param int $imageId + * @return int|bool New position id in database, false on error + */ public function add($userId, $trackId, $time, $lat, $lon, $altitude, $speed, $bearing, $accuracy, $provider, $comment, $imageId) { $positionId = false; if (!is_null($lat) && !is_null($lon) && !is_null($time) && !empty($userId) && !empty($trackId)) { @@ -77,6 +101,12 @@ class uPosition { return $positionId; } + /** + * Fill class properties with last position data from database + * (for given user if specified) + * + * @param int $userId Optional user id + */ public function getLast($userId = NULL) { if (!empty($userId)) { $where = "WHERE p.user_id = ?"; @@ -85,17 +115,24 @@ class uPosition { $where = ""; $params = NULL; } - $query = "SELECT p.id, p.time, p.user_id, p.track_id, - p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, - p.comment, p.image_id, u.login, t.name - FROM positions p - LEFT JOIN users u ON (p.user_id = u.id) - LEFT JOIN tracks t ON (p.track_id = t.id) + $query = "SELECT p.id, p.time, p.user_id, p.track_id, + p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, + p.comment, p.image_id, u.login, t.name + FROM positions p + LEFT JOIN users u ON (p.user_id = u.id) + LEFT JOIN tracks t ON (p.track_id = t.id) $where ORDER BY p.time DESC LIMIT 1"; $this->loadWithQuery($query, $params); } + /** + * Get array of all positions + * + * @param int $userId Optional limit to given user id + * @param int $trackId Optional limit to given track id + * @return array|bool Array of uPosition positions, false on error + */ public function getAll($userId = NULL, $trackId = NULL) { $rules = []; if (!empty($userId)) { @@ -103,19 +140,19 @@ class uPosition { } if (!empty($trackId)) { $rules[] = "p.track_id = '" . self::$db->real_escape_string($trackId) ."'"; - } + } if (!empty($rules)) { $where = "WHERE " . implode(" AND ", $rules); - } else { + } else { $where = ""; } - $query = "SELECT p.id, p.time, p.user_id, p.track_id, - p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, - p.comment, p.image_id, u.login, t.name - FROM positions p - LEFT JOIN users u ON (p.user_id = u.id) - LEFT JOIN tracks t ON (p.track_id = t.id) - $where + $query = "SELECT p.id, p.time, p.user_id, p.track_id, + p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider, + p.comment, p.image_id, u.login, t.name + FROM positions p + LEFT JOIN users u ON (p.user_id = u.id) + LEFT JOIN tracks t ON (p.track_id = t.id) + $where ORDER BY p.time"; $result = self::$db->query($query); if ($result === false) { @@ -129,7 +166,12 @@ class uPosition { return $positionsArr; } - // haversine distance to target point + /** + * Calculate distance to target point using haversine formula + * + * @param uPosition $target Target position + * @return int Distance in meters + */ public function distanceTo($target) { $lat1 = deg2rad($this->latitude); $lon1 = deg2rad($this->longitude); @@ -141,10 +183,22 @@ class uPosition { return $bearing * 6371000; } + /** + * Calculate time elapsed since target point + * + * @param uPosition $target Target position + * @return int Number of seconds + */ public function secondsTo($target) { return strtotime($this->time) - strtotime($target->time); } + /** + * Convert database row to uPosition + * + * @param array $row Row + * @return uPosition Position + */ private function rowToObject($row) { $position = new uPosition(); $position->id = $row['id']; @@ -166,25 +220,31 @@ class uPosition { return $position; } + /** + * Fill class properties with database query result + * + * @param string $query Query + * @param array|null $bindParams Optional array of bind parameters (types, params) + */ private function loadWithQuery($query, $bindParams = NULL) { - $stmt = self::$db->prepare($query); - if (is_array($bindParams) && ($types = array_shift($bindParams))) { - call_user_func_array( - [ $stmt, 'bind_param' ], - array_merge([ $types ], array_map(function(&$param) { return $param; }, $bindParams)) - ); + $stmt = self::$db->prepare($query); + if (is_array($bindParams) && ($types = array_shift($bindParams))) { + call_user_func_array( + [ $stmt, 'bind_param' ], + array_merge([ $types ], array_map(function(&$param) { return $param; }, $bindParams)) + ); + } + if ($stmt->execute()) { + $stmt->bind_result($this->id, $this->time, $this->userId, $this->trackId, + $this->latitude, $this->longitude, $this->altitude, $this->speed, + $this->bearing, $this->accuracy, $this->provider, + $this->comment, $this->imageId, $this->userLogin, $this->trackName); + if ($stmt->fetch()) { + $this->isValid = true; } - if ($stmt->execute()) { - $stmt->bind_result($this->id, $this->time, $this->userId, $this->trackId, - $this->latitude, $this->longitude, $this->altitude, $this->speed, - $this->bearing, $this->accuracy, $this->provider, - $this->comment, $this->imageId, $this->userLogin, $this->trackName); - if ($stmt->fetch()) { - $this->isValid = true; - } - } - $stmt->close(); + } + $stmt->close(); } -} + } ?> \ No newline at end of file diff --git a/helpers/track.php b/helpers/track.php index 1bddb44..0988ce7 100644 --- a/helpers/track.php +++ b/helpers/track.php @@ -17,9 +17,12 @@ * along with this program; if not, see . */ -require_once(__DIR__ . "/db.php"); + require_once(__DIR__ . "/db.php"); -class uTrack { + /** + * Track handling + */ + class uTrack { public $id; public $userId; public $name; @@ -29,6 +32,11 @@ class uTrack { private static $db; + /** + * Constructor + * + * @param int $trackId Track id + */ public function __construct($trackId = NULL) { self::$db = uDB::getInstance(); @@ -46,6 +54,14 @@ class uTrack { } } + /** + * Add new track + * + * @param string $userId User id + * @param string $name Name + * @param string $comment Optional comment + * @return int|bool New track id, false on error + */ public function add($userId, $name, $comment = NULL) { $trackId = false; if (!empty($userId) && !empty($name)) { @@ -61,6 +77,12 @@ class uTrack { return $trackId; } + /** + * Get all tracks + * + * @param int $userId Optional limit to user id + * @return array|bool Array of uTrack tracks, false on error + */ public function getAll($userId = NULL) { if (!empty($userId)) { $where = "WHERE user_id='" . self::$db->real_escape_string($userId) ."'"; @@ -80,6 +102,12 @@ class uTrack { return $trackArr; } + /** + * Convert database row to uTrack + * + * @param array $row Row + * @return uTrack Track + */ private function rowToObject($row) { $track = new uTrack(); $track->id = $row['id']; @@ -89,6 +117,6 @@ class uTrack { $track->isValid = true; return $track; } -} + } ?> \ No newline at end of file diff --git a/helpers/user.php b/helpers/user.php index 0d2cbb3..4d4324d 100644 --- a/helpers/user.php +++ b/helpers/user.php @@ -16,11 +16,13 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ + require_once (__DIR__ . "/config.php"); + require_once (__DIR__ . "/db.php"); -require_once(__DIR__ . "/config.php"); -require_once(__DIR__ . "/db.php"); - -class uUser { + /** + * User handling routines + */ + class uUser { public $id; public $login; public $hash; @@ -29,6 +31,11 @@ class uUser { private static $db; + /** + * Constructor + * + * @param string $login Login + */ public function __construct($login = NULL) { self::$db = uDB::getInstance(); if (!empty($login)) { @@ -44,6 +51,13 @@ class uUser { } } + /** + * Add new user + * + * @param string $login Login + * @param string $hash Password hash + * @return int|bool New user id, false on error + */ public function add($login, $hash) { $userid = false; if (!empty($login) && !empty($hash)) { @@ -59,6 +73,12 @@ class uUser { return $userid; } + /** + * Set user password + * + * @param string $hash Hash + * @return bool True on success, false otherwise + */ public function setPass($hash) { $ret = false; $sql = "UPDATE users SET password = ? WHERE login = ?"; @@ -72,14 +92,26 @@ class uUser { return $ret; } + /** + * Check if given password matches user's one + * + * @param String $password Password + * @return bool True if matches, false otherwise + */ public function validPassword($password) { return password_verify($password, $this->hash); } + /** + * Store uUser object in session + */ public function storeInSession() { $_SESSION['user'] = $this; } + /** + * Fill uUser object properties from session data + */ public function getFromSession() { if (isset($_SESSION['user'])) { $sessionUser = $_SESSION['user']; @@ -91,6 +123,11 @@ class uUser { } } + /** + * Get all users + * + * @return array|bool Array of uUser users, false on error + */ public function getAll() { $query = "SELECT id, login, password FROM users ORDER BY login"; $result = self::$db->query($query); @@ -105,6 +142,12 @@ class uUser { return $userArr; } + /** + * Convert database row to uUser + * + * @param array $row Row + * @return uUser User + */ private function rowToObject($row) { $user = new uUser(); $user->id = $row['id']; @@ -115,10 +158,15 @@ class uUser { return $user; } + /** + * Is given login admin user + * + * @param string $login Login + * @return bool True if admin, false otherwise + */ private function isAdmin($login) { $config = new uConfig(); return (!empty($config::$admin_user) && $config::$admin_user == $login); } -} - - ?> \ No newline at end of file + } +?> \ No newline at end of file diff --git a/index.php b/index.php index 8d5049b..ea37a69 100755 --- a/index.php +++ b/index.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + require_once("auth.php"); require_once("helpers/position.php"); require_once("helpers/track.php"); @@ -52,7 +52,7 @@ if ($user->isAdmin || $config::$public_tracks) { if ($lastPosition->isValid) { $lastUserId = $lastPosition->userId; } - + $usersArr = $user->getAll(); if (!empty($usersArr)) { foreach ($usersArr as $aUser) { diff --git a/lang.php b/lang.php index 199b669..1b5c7c8 100755 --- a/lang.php +++ b/lang.php @@ -16,9 +16,9 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + // available languages - $langsArr = [ + $langsArr = [ "en" => "English", "pl" => "Polski", "de" => "Deutsch", diff --git a/lang/de.php b/lang/de.php index ab46c3e..70a8727 100644 --- a/lang/de.php +++ b/lang/de.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + $lang["title"] = "• μlogger •"; $lang["private"] = "Sie müssen Benutzernamen und Kennwort eingeben, um auf diese Seite zuzugreifen."; $lang["authfail"] = "Falscher Benutzername oder Passwort"; diff --git a/lang/en.php b/lang/en.php index d63ca9c..43ac42c 100644 --- a/lang/en.php +++ b/lang/en.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + // default language for translations $lang["title"] = "• μlogger •"; diff --git a/lang/es.php b/lang/es.php index 1abc21a..4e6dbad 100644 --- a/lang/es.php +++ b/lang/es.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + $lang["title"] = "• μlogger •"; $lang["private"] = "Necesitas un nombre de usuario y contraseña para acceder a esta página."; $lang["authfail"] = "Nombre de usuasrio o contraseña erroneos"; diff --git a/lang/fr.php b/lang/fr.php index f2bab75..779016a 100644 --- a/lang/fr.php +++ b/lang/fr.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + $lang["title"] = "• μlogger •"; $lang["private"] = "Il faut un nom d'utilisateur et un mot de passe pour accéder à cette page."; $lang["authfail"] = "Nom d'utilisateur ou mot de passe erroné."; diff --git a/lang/hu.php b/lang/hu.php index 36281c0..f3e789d 100644 --- a/lang/hu.php +++ b/lang/hu.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + $lang["title"] = "• μlogger •"; $lang["private"] = "Felhasználónév és jelszó szükséges a belépéshez"; $lang["authfail"] = "Hibás név vagy jelszó"; diff --git a/lang/pl.php b/lang/pl.php index b604f3f..5e3e49d 100644 --- a/lang/pl.php +++ b/lang/pl.php @@ -16,7 +16,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - $lang["title"] = "• μlogger •"; $lang["private"] = "Aby się zalogować musisz podać login i hasło"; diff --git a/logout.php b/logout.php index 83d8d8f..46f25b0 100755 --- a/logout.php +++ b/logout.php @@ -16,7 +16,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + session_name('ulogger'); session_start(); $_SESSION = NULL; @@ -27,4 +27,5 @@ session_destroy(); $ssl = ((!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "" || $_SERVER['HTTPS'] == "off") ? "http" : "https"); $url = str_replace("//", "/", $_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME'])."/index.php"); header("Location: $ssl://$url"); -?> + +?> \ No newline at end of file diff --git a/main.css b/main.css index 1ab2da2..72f6b76 100755 --- a/main.css +++ b/main.css @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ - + html { height: 100%; } @@ -195,8 +195,8 @@ select { } .mi { - color:white; - padding-right:0.1em; + color:white; + padding-right:0.1em; font-style:italic; } @@ -259,7 +259,7 @@ select { -webkit-border-radius: 5px; } -button { +button { cursor: pointer; } diff --git a/main.js b/main.js index 4bd8a81..d21533b 100755 --- a/main.js +++ b/main.js @@ -16,8 +16,8 @@ * along with this program; if not, see . */ - // general stuff -if (units=='imperial') { +// general stuff +if (units == 'imperial') { factor_kmh = 0.62; //to mph unit_kmh = 'mph'; factor_m = 3.28; // to feet @@ -45,12 +45,12 @@ function displayChart() { data.addColumn('number', 'id'); data.addColumn('number', 'altitude'); var altLen = altitudes.length; - for (var i=0; i0) { + if (positions.length > 0) { clearMap(); - displayTrack(xml,update); + displayTrack(xml, update); } xhr = null; } } - xhr.open('GET','getpositions.php?trackid='+trackid+'&userid='+userid,true); + 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 + // 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 + var speed = getNode(p, 'speed'); // may be null if (speed != null) { speed = parseInt(speed); } - var bearing = getNode(p,'bearing'); // may be null + var bearing = getNode(p, 'bearing'); // may be null if (bearing != null) { bearing = parseInt(bearing); } - var accuracy = getNode(p,'accuracy'); // may be null + var accuracy = getNode(p, 'accuracy'); // may be null if (accuracy != null) { accuracy = parseInt(accuracy); } - var provider = getNode(p,'provider'); // may be null - var comments = getNode(p,'comments'); // may be null - 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')); + var provider = getNode(p, 'provider'); // may be null + var comments = getNode(p, 'comments'); // may be null + 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, @@ -174,88 +174,97 @@ function getPopupHtml(p, i, count) { var time = dateTime[1]; var provider = ''; if (p.provider == 'gps') { - provider = ' ('+lang['gps']+')'; + provider = ' (' + lang['gps'] + ')'; } else if (p.provider == 'network') { - provider = ' ('+lang['network']+')'; + provider = ' (' + lang['network'] + ')'; } - popup = - ''; + var stats = ''; + if (latest == 0) { + stats = + '
' + + '
' + + '' + lang['ttime'] + ' ' + + p.totalSeconds.toHMS() + '
' + + '' + lang['aspeed'] + ' ' + + ((p.totalSeconds > 0) ? ((p.totalMeters / p.totalSeconds).toKmH() * factor_kmh).toFixed() : 0) + ' ' + unit_kmh + '
' + + '' + lang['tdistance'] + ' ' + + (p.totalMeters.toKm() * factor_km).toFixed(2) + ' ' + unit_km + '
' + '
'; + } + popup = + ''; return popup; } -function load(type,userid,trackid) { - var url = 'download.php?type='+type+'&userid='+userid+'&trackid='+trackid; +function load(type, userid, trackid) { + var url = 'download.php?type=' + type + '&userid=' + userid + '&trackid=' + trackid; window.location.assign(url); } -function updateSummary(l,d,s) { +function updateSummary(l, d, s) { var t = document.getElementById('summary'); - if (latest==0){ - t.innerHTML = ''+lang['summary']+'
'+ - ''+lang['tdistance']+' '+(d.toKm()*factor_km).toFixed(2)+' '+unit_km+''+ - ''+lang['ttime']+' '+s.toHMS()+''; + if (latest == 0) { + t.innerHTML = '' + lang['summary'] + '
' + + '' + lang['tdistance'] + ' ' + (d.toKm() * factor_km).toFixed(2) + ' ' + unit_km + '' + + '' + lang['ttime'] + ' ' + s.toHMS() + ''; } else { - t.innerHTML = ''+lang['latest']+':
'+l; + t.innerHTML = '' + lang['latest'] + ':
' + l; } } -function getNode(p,name) { +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(){ +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)) + ''; + 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; +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; +Number.prototype.toKmH = function () { + return Math.round(this * 3600 / 10) / 100; } // negate value function toggleLatest() { - if (latest==0) { + if (latest == 0) { latest = 1; - loadTrack(userid,0,1); + loadTrack(userid, 0, 1); } else { latest = 0; - loadTrack(userid,trackid,1); + loadTrack(userid, trackid, 1); } } @@ -264,31 +273,31 @@ function setTrack(t) { } function selectTrack(f) { - trackid=f.options[f.selectedIndex].value; + trackid = f.options[f.selectedIndex].value; document.getElementById('latest').checked = false; - if (latest==1) { toggleLatest(); } - loadTrack(userid,trackid,1); + if (latest == 1) { toggleLatest(); } + loadTrack(userid, trackid, 1); } function selectUser(f) { - userid=f.options[f.selectedIndex].value; - if (f.options[0].disabled==false) { + 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(); } + if (latest == 1) { toggleLatest(); } getTracks(userid); } function getTracks(userid) { var xhr = getXHR(); - xhr.onreadystatechange = function() { - if (xhr.readyState==4 && xhr.status==200) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4 && xhr.status == 200) { var xml = xhr.responseXML; - var trackSelect = document.getElementsByName('track')[0]; + var trackSelect = document.getElementsByName('track')[0]; clearOptions(trackSelect); var tracks = xml.getElementsByTagName('track'); - if (tracks.length>0) { + if (tracks.length > 0) { fillOptions(xml); } else { clearMap(); @@ -296,27 +305,27 @@ function getTracks(userid) { xhr = null; } } - xhr.open('GET','gettracks.php?userid='+userid,true); + xhr.open('GET', 'gettracks.php?userid=' + userid, true); xhr.send(); } function fillOptions(xml) { - var trackSelect = document.getElementsByName('track')[0]; + var trackSelect = document.getElementsByName('track')[0]; var tracks = xml.getElementsByTagName('track'); var trackLen = tracks.length; - for (var i=0; i5000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; } - if (loadedAPI!==api) { - setTimeout(function() { loadTime += 50; waitAndLoad(api,url); }, 50); + if (loadTime > 5000) { loadTime = 0; alert('Sorry, can\'t load ' + api + ' API'); return; } + if (loadedAPI !== api) { + setTimeout(function () { loadTime += 50; waitAndLoad(api, url); }, 50); return; } - if(!isScriptLoaded(url[1])){ + if (!isScriptLoaded(url[1])) { addScript(url[1]); } loadTime = 0; @@ -386,26 +396,26 @@ function waitAndLoad(api,url) { function waitAndInit(api) { // wait till main api loads - if (loadTime>10000) { loadTime = 0; alert('Sorry, can\'t load '+api+' API'); return; } + if (loadTime > 10000) { loadTime = 0; alert('Sorry, can\'t load ' + api + ' API'); return; } try { init(); } - catch(e) { - setTimeout(function() { loadTime += 50; waitAndInit(api); }, 50); + catch (e) { + setTimeout(function () { loadTime += 50; waitAndInit(api); }, 50); return; } loadTime = 0; zoomToBounds(savedBounds); - loadTrack(userid,trackid,0); + loadTrack(userid, trackid, 0); // save current api as default - setCookie('api',api,30); + setCookie('api', api, 30); } function addScript(url) { var tag = document.createElement('script'); - tag.setAttribute('type','text/javascript'); + tag.setAttribute('type', 'text/javascript'); tag.setAttribute('src', url); - if (typeof tag!='undefined') { + if (typeof tag != 'undefined') { document.getElementsByTagName('head')[0].appendChild(tag); } } @@ -414,32 +424,32 @@ function isScriptLoaded(url) { scripts = document.getElementsByTagName('script'); for (var i = scripts.length; i--;) { // check if url matches src - var scriptUrl = scripts[i].src.replace(/https?:/,''); + var scriptUrl = scripts[i].src.replace(/https?:/, ''); if (scriptUrl != '' && url.indexOf(scriptUrl) !== -1) return true; } return false; } -function setCookie(name,value,days) { +function setCookie(name, value, days) { if (days) { var date = new Date(); - date.setTime(date.getTime()+(days*24*60*60*1000)); - var expires = '; expires='+date.toGMTString(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + var expires = '; expires=' + date.toGMTString(); } else { var expires = ''; } - document.cookie = 'ulogger_'+name+'='+value+expires+'; path=/'; + document.cookie = 'ulogger_' + name + '=' + value + expires + '; path=/'; } function setLang(lang) { - setCookie('lang',lang,30); + setCookie('lang', lang, 30); location.reload(); } function setUnits(unit) { units = unit; - setCookie('units',unit,30); + setCookie('units', unit, 30); location.reload(); } @@ -463,7 +473,7 @@ function userMenu() { } else { dropdown.classList.add('show'); window.addEventListener('click', removeOnClick, true); - } + } } function removeOnClick(event) { diff --git a/pass.js b/pass.js index 0bfeeca..1194430 100644 --- a/pass.js +++ b/pass.js @@ -40,12 +40,12 @@ function submitPass() { return; } var xhr = getXHR(); - xhr.onreadystatechange = function() { - if (xhr.readyState==4 && xhr.status==200) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4 && xhr.status == 200) { var xml = xhr.responseXML; var message = ""; if (xml) { - var root = xml.getElementsByTagName('root'); + var root = xml.getElementsByTagName('root'); if (root.length && getNode(root[0], 'error') == 0) { removeModal(); alert("Password successfully changed"); diff --git a/scripts/migrate_from_phptrackme.php b/scripts/migrate_from_phptrackme.php index 3e73e20..1e1b0d3 100644 --- a/scripts/migrate_from_phptrackme.php +++ b/scripts/migrate_from_phptrackme.php @@ -21,10 +21,10 @@ * * However, as μlogger users more secure password storage methods, * it is impossible to convert old password hashes to the new format. - * Administrator will have to fill in user passwords manually. - * Alternatively authentication code could be modify in order to - * temporarily accept old hashes and convert it as users log in. - * It should be pretty simple, but this is not a top priority + * Administrator will have to fill in user passwords manually. + * Alternatively authentication code could be modify in order to + * temporarily accept old hashes and convert it as users log in. + * It should be pretty simple, but this is not a top priority * for this small project. */