diff --git a/.docker/init.sh b/.docker/init.sh
index 714d920..377ccd1 100644
--- a/.docker/init.sh
+++ b/.docker/init.sh
@@ -6,6 +6,10 @@ DB_USER_PASS=$2
mkdir -p /run/nginx
chown nginx:nginx /run/nginx
+# Fix permission issues on mounted volume in macOS
+sed -i "s/^nobody:.*$/nobody:x:1000:50::nobody:\/:\/sbin\/nologin/" /etc/passwd
+sed -i "s/^nobody:.*$/nobody:x:50:/" /etc/group
+
sed -i "s/^\$dbuser = .*$/\$dbuser = \"ulogger\";/" /var/www/html/config.php
sed -i "s/^\$dbpass = .*$/\$dbpass = \"${DB_USER_PASS}\";/" /var/www/html/config.php
@@ -28,7 +32,11 @@ if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then
su postgres -c "pg_ctl -w stop"
sed -i "s/^\$dbdsn = .*$/\$dbdsn = \"pgsql:host=localhost;port=5432;dbname=ulogger\";/" /var/www/html/config.php
elif [ "$ULOGGER_DB_DRIVER" = "sqlite" ]; then
- sqlite3 /data/ulogger.db < /var/www/html/scripts/ulogger.sqlite
+ mkdir -p /data
+ chown nobody:nobody /data
+ sqlite3 -init /var/www/html/scripts/ulogger.sqlite /data/ulogger.db
+ sqlite3 -line /data/ulogger.db "INSERT INTO users (login, password) VALUES ('admin', '\$2y\$10\$7OvZrKgonVZM9lkzrTbiou.CVhO3HjPk5y0W9L68fVwPs/osBRIMq')"
+ sed -i "s/^\$dbdsn = .*$/\$dbdsn = \"sqlite:\/data\/sqlite\/ulogger.db\";/" /var/www/html/config.php
else
mkdir -p /run/mysqld
chown mysql:mysql /run/mysqld
diff --git a/.docker/run.sh b/.docker/run.sh
index 5dda0fe..3e1856c 100644
--- a/.docker/run.sh
+++ b/.docker/run.sh
@@ -18,7 +18,7 @@ grep '^\$' /var/www/html/config.php
# start services
if [ "$ULOGGER_DB_DRIVER" = "pgsql" ]; then
su postgres -c 'pg_ctl -D /data start'
-else
+elif [ "$ULOGGER_DB_DRIVER" = "mysql" ]; then
mysqld_safe --datadir=/data &
fi
nginx
diff --git a/.tests/fixtures/fixture_admin.xml b/.tests/fixtures/fixture_admin.xml
index a8319bb..2abb77c 100644
--- a/.tests/fixtures/fixture_admin.xml
+++ b/.tests/fixtures/fixture_admin.xml
@@ -1,17 +1,6 @@
-
-
-
-
-
-
-
-
-
-
- 1
- admin
- $2y$10$7OvZrKgonVZM9lkzrTbiou.CVhO3HjPk5y0W9L68fVwPs/osBRIMq
-
-
-
-
+
+
+
+
+
+
diff --git a/.tests/fixtures/fixture_empty.xml b/.tests/fixtures/fixture_empty.xml
index 764cc13..4a92520 100644
--- a/.tests/fixtures/fixture_empty.xml
+++ b/.tests/fixtures/fixture_empty.xml
@@ -1,11 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/.tests/lib/BaseDatabaseTestCase.php b/.tests/lib/BaseDatabaseTestCase.php
index 5d17f5e..b321b79 100644
--- a/.tests/lib/BaseDatabaseTestCase.php
+++ b/.tests/lib/BaseDatabaseTestCase.php
@@ -37,7 +37,6 @@ abstract class BaseDatabaseTestCase extends PHPUnit_Extensions_Database_TestCase
public function setUp() {
parent::setUp();
-
}
public static function setUpBeforeClass() {
@@ -81,15 +80,19 @@ abstract class BaseDatabaseTestCase extends PHPUnit_Extensions_Database_TestCase
* @return PHPUnit_Extensions_Database_DataSet_IDataSet
*/
protected function getDataSet() {
- $this->resetSequences();
- return $this->createMySQLXMLDataSet(__DIR__ . '/../fixtures/fixture_empty.xml');
+ $this->resetAutoincrement();
+ return $this->createFlatXMLDataSet(__DIR__ . '/../fixtures/fixture_empty.xml');
}
- protected function resetSequences($users = 1, $tracks = 1, $positions = 1) {
+ protected function resetAutoincrement($users = 1, $tracks = 1, $positions = 1) {
if (self::$driver == "pgsql") {
self::$pdo->query("ALTER SEQUENCE users_id_seq RESTART WITH $users");
self::$pdo->query("ALTER SEQUENCE tracks_id_seq RESTART WITH $tracks");
self::$pdo->query("ALTER SEQUENCE positions_id_seq RESTART WITH $positions");
+ } else if (self::$driver == "sqlite") {
+ self::$pdo->query("DELETE FROM sqlite_sequence WHERE NAME = 'users'");
+ self::$pdo->query("DELETE FROM sqlite_sequence WHERE NAME = 'tracks'");
+ self::$pdo->query("DELETE FROM sqlite_sequence WHERE NAME = 'positions'");
}
}
@@ -224,7 +227,7 @@ abstract class BaseDatabaseTestCase extends PHPUnit_Extensions_Database_TestCase
return "TO_TIMESTAMP($column)";
break;
case "sqlite":
- return "DATE($column, 'unixepoch')";
+ return "DATETIME($column, 'unixepoch')";
break;
}
}
diff --git a/.tests/lib/UloggerAPITestCase.php b/.tests/lib/UloggerAPITestCase.php
index b44c986..0bd4fb4 100644
--- a/.tests/lib/UloggerAPITestCase.php
+++ b/.tests/lib/UloggerAPITestCase.php
@@ -26,8 +26,8 @@ class UloggerAPITestCase extends BaseDatabaseTestCase {
}
protected function getDataSet() {
- $this->resetSequences(2);
- return $this->createMySQLXMLDataSet(__DIR__ . '/../fixtures/fixture_admin.xml');
+ $this->resetAutoincrement(2);
+ return $this->createFlatXMLDataSet(__DIR__ . '/../fixtures/fixture_admin.xml');
}
/**
diff --git a/.tests/tests/ClientAPITest.php b/.tests/tests/ClientAPITest.php
index 445a4a1..1b99e8d 100644
--- a/.tests/tests/ClientAPITest.php
+++ b/.tests/tests/ClientAPITest.php
@@ -43,7 +43,6 @@ class ClientAPITest extends UloggerAPITestCase {
public function testAddUser() {
$this->assertTrue($this->authenticate(), "Authentication failed");
-
$this->assertEquals(1, $this->getConnection()->getRowCount('users'), "Wrong row count");
$options = [
diff --git a/helpers/db.php b/helpers/db.php
index 8ec3c5b..195589d 100644
--- a/helpers/db.php
+++ b/helpers/db.php
@@ -37,6 +37,13 @@
*/
protected static $tables;
+ /**
+ * Database driver name
+ *
+ * @var String Driver
+ */
+ protected static $driver;
+
/**
* PDO constuctor
*
@@ -52,6 +59,7 @@
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // return assoc array by default
];
@parent::__construct($dsn, $user, $pass, $options);
+ self::$driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->setCharset("utf8");
$this->initTables();
} catch (PDOException $e) {
@@ -94,8 +102,7 @@
}
public function unix_timestamp($column) {
- $driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
- switch ($driver) {
+ switch (self::$driver) {
default:
case "mysql":
return "UNIX_TIMESTAMP($column)";
@@ -110,8 +117,7 @@
}
public function from_unixtime($column) {
- $driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
- switch ($driver) {
+ switch (self::$driver) {
default:
case "mysql":
return "FROM_UNIXTIME($column)";
@@ -120,13 +126,15 @@
return "TO_TIMESTAMP($column)";
break;
case "sqlite":
- return "DATE($column, 'unixepoch')";
+ return "DATETIME($column, 'unixepoch')";
break;
}
}
private function setCharset($charset) {
- $this->query("SET NAMES '$charset'");
+ if (self::$driver == "pgsql" || self::$driver == "mysql") {
+ $this->query("SET NAMES '$charset'");
+ }
}
}
?>
diff --git a/helpers/utils.php b/helpers/utils.php
index 98b92c7..2fbe3ff 100644
--- a/helpers/utils.php
+++ b/helpers/utils.php
@@ -142,11 +142,11 @@
}
public static function postString($name, $default = NULL) {
- if (is_string(($val = self::requestValue($name, $default, INPUT_POST)))) {
- return trim($val);
- } else {
- return $val;
- }
+ return self::requestString($name, $default, INPUT_POST);
+ }
+
+ public static function getString($name, $default = NULL) {
+ return self::requestString($name, $default, INPUT_GET);
}
public static function getBool($name, $default = NULL) {
@@ -154,22 +154,30 @@
}
public static function postInt($name, $default = NULL) {
- if (is_float(($val = self::postFloat($name, $default)))) {
- return (int) round($val);
- } else {
- return self::requestValue($name, $default, INPUT_POST, FILTER_VALIDATE_INT);
- }
+ return self::requestInt($name, $default, INPUT_POST);
}
public static function getInt($name, $default = NULL) {
- if (is_float(($val = self::getFloat($name, $default)))) {
- return (int) round($val);
+ return self::requestInt($name, $default, INPUT_GET);
+ }
+
+ private static function requestString($name, $default, $type) {
+ if (is_string(($val = self::requestValue($name, $default, $type)))) {
+ return trim($val);
} else {
- return self::requestValue($name, $default, INPUT_GET, FILTER_VALIDATE_INT);
+ return $val;
}
}
- public static function requestValue($name, $default = NULL, $type = INPUT_POST, $filters = FILTER_DEFAULT, $flags = NULL) {
+ private static function requestInt($name, $default, $type) {
+ if (is_float(($val = self::requestValue($name, $default, $type, FILTER_VALIDATE_FLOAT)))) {
+ return (int) round($val);
+ } else {
+ return self::requestValue($name, $default, $type, FILTER_VALIDATE_INT);
+ }
+ }
+
+ private static function requestValue($name, $default, $type, $filters = FILTER_DEFAULT, $flags = NULL) {
$input = filter_input($type, $name, $filters, $flags);
if ($input !== false && !is_null($input)) {
return $input;
diff --git a/scripts/setup.php b/scripts/setup.php
index aa4990b..e3aedff 100644
--- a/scripts/setup.php
+++ b/scripts/setup.php
@@ -18,7 +18,7 @@
*/
// This script is disabled by default. Change below to true before running.
-$enabled = true;
+$enabled = false;
/* -------------------------------------------- */
@@ -31,6 +31,7 @@ if (version_compare(PHP_VERSION, '5.4.0', '<')) {
define("ROOT_DIR", dirname(__DIR__));
require_once(ROOT_DIR . "/helpers/user.php");
require_once(ROOT_DIR . "/helpers/config.php");
+require_once(ROOT_DIR . "/helpers/utils.php");
require_once(ROOT_DIR . "/lang.php");
$command = uUtils::postString('command');
@@ -39,6 +40,7 @@ $prefix = preg_replace('/[^a-z0-9_]/i', '', uConfig::$dbprefix);
$tPositions = $prefix . "positions";
$tTracks = $prefix . "tracks";
$tUsers = $prefix . "users";
+$dbDriver = null;
$messages = [];
switch ($command) {
@@ -46,7 +48,9 @@ switch ($command) {
$error = false;
try {
- $db = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass);
+ $options = [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ];
+ $pdo = new PDO(uConfig::$dbdsn, uConfig::$dbuser, uConfig::$dbpass, $options);
+ $dbDriver = $pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
} catch (PDOException $e ) {
$messages[] = "{$langSetup["dbconnectfailed"]}";
$messages[] = sprintf($langSetup["serversaid"], "" . $e->getMessage() . "");
@@ -54,16 +58,16 @@ switch ($command) {
break;
}
try {
- $queries = getQueries($db);
+ $queries = getQueries($pdo);
foreach ($queries as $query) {
- $db->query($query);
+ $pdo->query($query);
}
} catch (PDOException $e) {
$messages[] = "{$langSetup["dbqueryfailed"]}";
$messages[] = sprintf($langSetup["serversaid"], "" . $e->getMessage() . "");
$error = true;
}
- $db = null;
+ $pdo = null;
if (!$error) {
$messages[] = "{$langSetup["dbtablessuccess"]}";
$messages[] = $langSetup["setupuser"];
@@ -114,22 +118,28 @@ switch ($command) {
$messages[] = "
";
break;
}
- if (empty(uConfig::$dbdsn) || empty(uConfig::$dbuser)) {
- $messages[] = sprintf($langSetup["nodbsettings"], "\$dbdsn, \$dbuser, \$dbpass");
+ if (empty(uConfig::$dbdsn) || ($dbDriver != "sqlite" && empty(uConfig::$dbuser))) {
+ if ($dbDriver == "sqlite") {
+ $required = "\$dbdsn";
+ } else {
+ $required = "\$dbdsn, \$dbuser, \$dbpass";
+ }
+ $messages[] = sprintf($langSetup["nodbsettings"], $required);
$messages[] = $langSetup["dorestart"];
$messages[] = "";
break;
}
- $messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", "" . uConfig::$dbname . "");
+ $messages[] = sprintf($langSetup["scriptdesc"], "'$tPositions', '$tTracks', '$tUsers'", "" . getDbname(uConfig::$dbdsn) . "");
$messages[] = $langSetup["scriptdesc2"];
$messages[] = "";
break;
}
-function getQueries($db) {
- $driver = $db->getAttribute(PDO::ATTR_DRIVER_NAME);
+function getQueries($pdo) {
+ global $tPositions, $tUsers, $tTracks, $dbDriver;
+
$queries = [];
- switch($driver) {
+ switch($dbDriver) {
case "mysql":
// users
$queries[] = "DROP TABLE IF EXISTS `$tUsers`";
@@ -262,6 +272,29 @@ function getQueries($db) {
default:
throw InvalidArgumentException("Driver not supported");
}
+ return $queries;
+}
+
+function getDbname($dsn) {
+ if (strpos($dsn, ':') !== false) {
+ list($scheme, $dsnWithoutScheme) = explode(':', $dsn, 2);
+ switch ($scheme) {
+ case 'sqlite':
+ case 'sqlite2':
+ case 'sqlite3':
+ return $dsnWithoutScheme;
+ break;
+
+ default:
+ $pattern = '~dbname=([^;]*)(?:;|$)~';
+ $result = preg_match($pattern, $dsnWithoutScheme, $matches);
+ if ($result === 1 && !empty($matches[1])) {
+ return $matches[1];
+ }
+ break;
+ }
+ }
+ return "noname";
}
?>
diff --git a/scripts/ulogger.sqlite b/scripts/ulogger.sqlite
new file mode 100644
index 0000000..2171d96
--- /dev/null
+++ b/scripts/ulogger.sqlite
@@ -0,0 +1,68 @@
+--
+-- Database: `ulogger`
+--
+
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `users`
+--
+
+DROP TABLE IF EXISTS `users`;
+CREATE TABLE `users` (
+ `id` integer PRIMARY KEY AUTOINCREMENT,
+ `login` varchar(15) NOT NULL UNIQUE,
+ `password` varchar(255) NOT NULL DEFAULT ''
+);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `tracks`
+--
+
+DROP TABLE IF EXISTS `tracks`;
+CREATE TABLE `tracks` (
+ `id` integer PRIMARY KEY AUTOINCREMENT,
+ `user_id` integer NOT NULL,
+ `name` varchar(255) DEFAULT NULL,
+ `comment` varchar(1024) DEFAULT NULL,
+ FOREIGN KEY(`user_id`) REFERENCES `users`(`id`)
+);
+CREATE INDEX `idx_user_id` ON `tracks`(`user_id`);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `positions`
+--
+
+DROP TABLE IF EXISTS `positions`;
+CREATE TABLE `positions` (
+ `id` integer PRIMARY KEY AUTOINCREMENT,
+ `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `user_id` integer NOT NULL,
+ `track_id` integer NOT NULL,
+ `latitude` double NOT NULL,
+ `longitude` double NOT NULL,
+ `altitude` double DEFAULT NULL,
+ `speed` double DEFAULT NULL,
+ `bearing` double DEFAULT NULL,
+ `accuracy` integer DEFAULT NULL,
+ `provider` varchar(100) DEFAULT NULL,
+ `comment` varchar(255) DEFAULT NULL,
+ `image_id` integer DEFAULT NULL,
+ FOREIGN KEY(`user_id`) REFERENCES `users`(`id`),
+ FOREIGN KEY(`track_id`) REFERENCES `tracks`(`id`)
+);
+CREATE INDEX `idx_ptrack_id` ON `positions`(`track_id`);
+CREATE INDEX `idx_puser_id` ON `positions`(`user_id`);
+
+--
+-- This will add default user admin with password admin
+-- The password should be changed immediatelly after installation
+-- Uncomment if needed
+--
+-- INSERT INTO `users` (`id`, `login`, `password`) VALUES
+-- (1, 'admin', '$2y$10$7OvZrKgonVZM9lkzrTbiou.CVhO3HjPk5y0W9L68fVwPs/osBRIMq');
diff --git a/utils/export.php b/utils/export.php
index db668ed..2f30666 100755
--- a/utils/export.php
+++ b/utils/export.php
@@ -57,9 +57,9 @@ function toHMS($s) {
return (($d > 0) ? "$d d " : "") . sprintf("%02d:%02d:%02d", $h, $m, $s);
}
-$type = uUtils::postString('type', 'kml');
-$userId = uUtils::postInt('userid');
-$trackId = uUtils::postInt('trackid');
+$type = uUtils::getString('type', 'kml');
+$userId = uUtils::getInt('userid');
+$trackId = uUtils::getInt('trackid');
if (!uConfig::$public_tracks &&
(!$auth->isAuthenticated() || (!$auth->isAdmin() && $auth->user->id !== $userId))) {