diff --git a/.tests/lib/BaseDatabaseTestCase.php b/.tests/lib/BaseDatabaseTestCase.php
index fcbb982..92bb68f 100644
--- a/.tests/lib/BaseDatabaseTestCase.php
+++ b/.tests/lib/BaseDatabaseTestCase.php
@@ -140,10 +140,10 @@ abstract class BaseDatabaseTestCase extends PHPUnit\DbUnit\TestCase {
*
* @param string $table Table name
* @param array $rowsArr Array of rows
- * @return int|null Last insert id if available, NULL otherwise
+ * @return int|null Last insert id if available, null otherwise
*/
private function pdoInsert(string $table, array $rowsArr = []): ?int {
- $ret = NULL;
+ $ret = null;
if (!empty($rowsArr)) {
$values = ':' . implode(', :', array_keys($rowsArr));
$columns = implode(', ', array_keys($rowsArr));
@@ -161,7 +161,7 @@ abstract class BaseDatabaseTestCase extends PHPUnit\DbUnit\TestCase {
* Execute raw insert query on database
*
* @param string $query Insert query
- * @return int|null Last insert id if available, NULL otherwise
+ * @return int|null Last insert id if available, null otherwise
*/
private function pdoInsertRaw(string $query): ?int {
$ret = null;
diff --git a/.tests/tests/InternalAPITest.php b/.tests/tests/InternalAPITest.php
index e6971f1..7456583 100644
--- a/.tests/tests/InternalAPITest.php
+++ b/.tests/tests/InternalAPITest.php
@@ -37,19 +37,19 @@ class InternalAPITest extends UloggerAPITestCase {
$position = $json[0];
self::assertEquals(1, (int) $position->id, "Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
$position = $json[1];
- self::assertEquals(2, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(2, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
}
/**
@@ -78,20 +78,20 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(2, $json, "Wrong count of positions");
$position = $json[0];
- self::assertEquals(1, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(1, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
$position = $json[1];
- self::assertEquals(2, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(2, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
}
/**
@@ -148,20 +148,20 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(2, $json, "Wrong count of positions");
$position = $json[0];
- self::assertEquals(1, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(1, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
$position = $json[1];
- self::assertEquals(2, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(2, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
}
/**
@@ -195,12 +195,12 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(1, $json, "Wrong count of positions");
$position = $json[0];
- self::assertEquals(2, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(2, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
}
/**
@@ -235,20 +235,20 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(2, $json, "Wrong count of positions");
$position = $json[0];
- self::assertEquals(2, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(2, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
$position = $json[1];
- self::assertEquals(3, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 2, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
- self::assertEquals($trackName, (string) $position->trackname,"Wrong trackname");
+ self::assertEquals(3, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 2, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
+ self::assertEquals($trackName, (string) $position->trackname, "Wrong trackname");
}
/**
@@ -349,14 +349,14 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(1, $json, "Wrong count of positions");
$position = $json[0];
- self::assertEquals($afterId + 1, (int) $position->id,"Wrong position id");
- self::assertEquals($this->testLat + 1, (float) $position->latitude,"Wrong latitude");
- self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
- self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
- self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
- self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
- self::assertEquals(111195, (int) $position->meters,"Wrong distance delta");
- self::assertEquals(1, (int) $position->seconds,"Wrong timestamp delta");
+ self::assertEquals($afterId + 1, (int) $position->id, "Wrong position id");
+ self::assertEquals($this->testLat + 1, (float) $position->latitude, "Wrong latitude");
+ self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
+ self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
+ self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
+ self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
+ self::assertEquals(111195, (int) $position->meters, "Wrong distance delta");
+ self::assertEquals(1, (int) $position->seconds, "Wrong timestamp delta");
}
@@ -387,12 +387,12 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(2, $json, "Wrong count of tracks");
$track = $json[0];
- self::assertEquals($this->testTrackId2, (int) $track->id,"Wrong track id");
- self::assertEquals($this->testTrackName . "2", (string) $track->name,"Wrong track name");
+ self::assertEquals($this->testTrackId2, (int) $track->id, "Wrong track id");
+ self::assertEquals($this->testTrackName . "2", (string) $track->name, "Wrong track name");
$track = $json[1];
- self::assertEquals($this->testTrackId, (int) $track->id,"Wrong track id");
- self::assertEquals($this->testTrackName, (string) $track->name,"Wrong track name");
+ self::assertEquals($this->testTrackId, (int) $track->id, "Wrong track id");
+ self::assertEquals($this->testTrackName, (string) $track->name, "Wrong track name");
}
/**
@@ -420,12 +420,12 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertCount(2, $json, "Wrong count of tracks");
$track = $json[0];
- self::assertEquals($this->testTrackId2, (int) $track->id,"Wrong track id");
- self::assertEquals($this->testTrackName . "2", (string) $track->name,"Wrong track name");
+ self::assertEquals($this->testTrackId2, (int) $track->id, "Wrong track id");
+ self::assertEquals($this->testTrackName . "2", (string) $track->name, "Wrong track name");
$track = $json[1];
- self::assertEquals($this->testTrackId, (int) $track->id,"Wrong track id");
- self::assertEquals($this->testTrackName, (string) $track->name,"Wrong track name");
+ self::assertEquals($this->testTrackId, (int) $track->id, "Wrong track id");
+ self::assertEquals($this->testTrackName, (string) $track->name, "Wrong track name");
}
/**
@@ -626,8 +626,8 @@ class InternalAPITest extends UloggerAPITestCase {
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals("Wrong old password", (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals("Wrong old password", (string) $json->message, "Wrong error message");
}
/**
@@ -871,8 +871,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
self::assertEquals(2, $this->getConnection()->getRowCount("tracks"), "Wrong row count");
}
@@ -899,8 +899,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
}
/**
@@ -918,7 +918,7 @@ class InternalAPITest extends UloggerAPITestCase {
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
self::assertEquals(1, (int) $json->error, "Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
}
@@ -938,8 +938,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
}
/**
@@ -959,8 +959,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
}
@@ -981,8 +981,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
self::assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count");
}
@@ -1002,8 +1002,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
self::assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count");
}
@@ -1024,8 +1024,8 @@ class InternalAPITest extends UloggerAPITestCase {
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
- self::assertEquals(1, (int) $json->error,"Wrong error status");
- self::assertEquals($lang["servererror"], (string) $json->message,"Wrong error message");
+ self::assertEquals(1, (int) $json->error, "Wrong error status");
+ self::assertEquals($lang["servererror"], (string) $json->message, "Wrong error message");
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
}
@@ -1074,7 +1074,7 @@ class InternalAPITest extends UloggerAPITestCase {
$json = json_decode($response->getBody());
self::assertNotNull($json, "JSON object is null");
self::assertEquals(1, (int) $json->error, "Wrong error status");
- self::assertEquals($lang["userexists"], (string) $json->message,"Wrong error message");
+ self::assertEquals($lang["userexists"], (string) $json->message, "Wrong error message");
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
}
diff --git a/.tests/tests/PositionTest.php b/.tests/tests/PositionTest.php
index c7f7a53..acac7d5 100644
--- a/.tests/tests/PositionTest.php
+++ b/.tests/tests/PositionTest.php
@@ -41,11 +41,11 @@ class PositionTest extends UloggerDatabaseTestCase {
);
$this->assertTableContains($expected, $actual, "Wrong actual table data");
- $posId = uPosition::add($userId, $trackId, NULL, $this->testLat, $this->testLon);
+ $posId = uPosition::add($userId, $trackId, null, $this->testLat, $this->testLon);
self::assertFalse($posId, "Adding position with null time stamp should fail");
- $posId = uPosition::add($userId, $trackId, $this->testTimestamp, NULL, $this->testLon);
+ $posId = uPosition::add($userId, $trackId, $this->testTimestamp, null, $this->testLon);
self::assertFalse($posId, "Adding position with null latitude should fail");
- $posId = uPosition::add($userId, $trackId, $this->testTimestamp, $this->testLat, NULL);
+ $posId = uPosition::add($userId, $trackId, $this->testTimestamp, $this->testLat, null);
self::assertFalse($posId, "Adding position with null longitude should fail");
$posId = uPosition::add($userId, $trackId, "", $this->testLat, $this->testLon);
@@ -156,7 +156,7 @@ class PositionTest extends UloggerDatabaseTestCase {
self::assertCount(2, $posArr, "Wrong row count");
$posArr = uPosition::getAll($userId, $trackId);
self::assertCount(1, $posArr, "Wrong row count");
- $posArr = uPosition::getAll(NULL, $trackId);
+ $posArr = uPosition::getAll(null, $trackId);
self::assertCount(1, $posArr, "Wrong row count");
$posArr = uPosition::getAll($userId3);
self::assertCount(0, $posArr, "Wrong row count");
diff --git a/.tests/tests/TrackTest.php b/.tests/tests/TrackTest.php
index 7dce897..700228c 100644
--- a/.tests/tests/TrackTest.php
+++ b/.tests/tests/TrackTest.php
@@ -72,11 +72,11 @@ class TrackTest extends UloggerDatabaseTestCase {
);
$this->assertTableContains($expected, $actual, "Wrong actual table data");
- $posId = $track->addPosition($userId, NULL, $this->testLat, $this->testLon);
+ $posId = $track->addPosition($userId, null, $this->testLat, $this->testLon);
self::assertFalse($posId, "Adding position with null time stamp should fail");
- $posId = $track->addPosition($userId, $this->testTimestamp, NULL, $this->testLon);
+ $posId = $track->addPosition($userId, $this->testTimestamp, null, $this->testLon);
self::assertFalse($posId, "Adding position with null latitude should fail");
- $posId = $track->addPosition($userId, $this->testTimestamp, $this->testLat, NULL);
+ $posId = $track->addPosition($userId, $this->testTimestamp, $this->testLat, null);
self::assertFalse($posId, "Adding position with null longitude should fail");
$posId = $track->addPosition($userId, "", $this->testLat, $this->testLon);
@@ -113,7 +113,7 @@ class TrackTest extends UloggerDatabaseTestCase {
uTrack::deleteAll($userId);
self::assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count");
self::assertEquals(1, $this->getConnection()->getRowCount('positions'), "Wrong row count");
- self::assertFalse(uTrack::deleteAll(NULL), "User id should not be empty");
+ self::assertFalse(uTrack::deleteAll(null), "User id should not be empty");
}
public function testUpdate(): void {
diff --git a/.tests/tests/UserTest.php b/.tests/tests/UserTest.php
index 4bad7cd..0a0c1c7 100644
--- a/.tests/tests/UserTest.php
+++ b/.tests/tests/UserTest.php
@@ -75,7 +75,7 @@ class UserTest extends UloggerDatabaseTestCase {
}
public function testIsAdmin(): void {
- $this->addTestUser($this->testUser, NULL, true);
+ $this->addTestUser($this->testUser, null, true);
$user = new uUser($this->testUser);
self::assertTrue($user->isAdmin, "User should be admin");
}
diff --git a/css/src/main.css b/css/src/main.css
index 1a704bd..0c65bf3 100644
--- a/css/src/main.css
+++ b/css/src/main.css
@@ -85,7 +85,7 @@ select {
width: 165px;
padding-left: 10px;
color: lightgray;
- background-color: rgba(102, 102, 102, 0.9);
+ background-color: rgba(102, 102, 102, 90%);
}
#menu-button {
@@ -122,7 +122,7 @@ select {
#menu.menu-hidden #menu-button {
font-weight: normal;
border-color: white;
- background-color: rgba(0, 60, 136, 0.3);
+ background-color: rgba(0, 60, 136, 30%);
}
#menu.menu-hidden #menu-button a::after {
@@ -153,7 +153,7 @@ select {
margin-top: 0.2em;
}
-label[for=user] {
+label[for="user"] {
display: block;
padding-top: 1em;
}
@@ -340,7 +340,7 @@ label[for=user] {
width: 100%;
height: 100%;
background-color: black; /* fallback */
- background-color: rgba(0, 0, 0, 0.4);
+ background-color: rgba(0, 0, 0, 40%);
}
#modal-header {
@@ -353,7 +353,7 @@ label[for=user] {
#modal-header button {
border: none;
- background-color: rgba(0, 0, 0, 0);
+ background-color: rgba(0, 0, 0, 0%);
}
#modal-body {
@@ -363,13 +363,13 @@ label[for=user] {
transform: translate(-50%, -50%) !important;
font-size: 0.9em;
min-width: 300px;
- margin: 0 auto 15% auto;
+ margin: 0 auto 15%;
padding: 1em;
color: white;
border: 1px solid #888;
-webkit-border-radius: 10px;
border-radius: 10px;
- background-color: rgba(102, 102, 102, 0.9);
+ background-color: rgba(102, 102, 102, 90%);
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
}
@@ -378,10 +378,10 @@ label[for=user] {
padding-top: 1em;
}
-#modal input[type=text],
-#modal input[type=color],
-#modal input[type=number],
-#modal input[type=password] {
+#modal input[type="text"],
+#modal input[type="color"],
+#modal input[type="number"],
+#modal input[type="password"] {
display: inline-block;
box-sizing: border-box;
width: 100%;
@@ -395,7 +395,7 @@ label[for=user] {
#modal.image {
overflow: hidden;
padding-top: 0;
- background-color: rgba(45, 45, 45, 0.95);
+ background-color: rgba(45, 45, 45, 95%);
}
#modal.image #modal-body img {
@@ -466,11 +466,11 @@ button > * {
text-decoration: underline;
}
-#configForm label {
+#config-form label {
display: block;
}
-#configForm label b {
+#config-form label b {
display: inline-block;
text-align: right;
width: 250px;
@@ -479,30 +479,30 @@ button > * {
padding-top: 5px;
}
-#configForm input[type=text],
-#configForm input[type=number],
-#configForm input[type=color],
-#configForm select {
+#config-form input[type="text"],
+#config-form input[type="number"],
+#config-form input[type="color"],
+#config-form select {
width: 150px;
margin: 3px 0;
padding: 2px 4px;
box-sizing: border-box;
}
-#configForm input[type=checkbox] {
+#config-form input[type="checkbox"] {
margin: 0;
}
-#configForm select {
+#config-form select {
padding: 2px 0;
}
-#configForm input[type=color] {
+#config-form input[type="color"] {
vertical-align: middle;
padding: 0;
}
-#configForm img {
+#config-form img {
height: 13px;
vertical-align: middle;
margin: 0 5px;
@@ -531,7 +531,7 @@ button > * {
padding: 6px 20px;
border-radius: 5px;
border-top: 1px solid #555;
- box-shadow: 10px 10px 10px -8px rgba(0, 0, 0, 0.3);
+ box-shadow: 10px 10px 10px -8px rgba(0, 0, 0, 30%);
z-index: 100000;
opacity: 0;
transition: all 1s;
@@ -596,7 +596,7 @@ button > * {
}
.alert.spinner > span::before, .alert.spinner > span::after {
- content: '';
+ content: "";
display: inline-block;
position: absolute;
top: 0;
@@ -661,8 +661,8 @@ button > * {
border: 1px solid #ccc;
border-radius: 10px;
background-color: #666;
- -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
- filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+ -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 20%));
+ filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 20%));
}
.ol-popup::after, .ol-popup::before {
@@ -695,7 +695,7 @@ button > * {
right: -10px;
width: 30px;
height: 30px;
- background-image: url(../../images/close.svg) !important;
+ background-image: url("../../images/close.svg") !important;
background-repeat: no-repeat !important;
}
@@ -710,11 +710,12 @@ button > * {
}
.gm-style .gm-style-iw-t::after {
- background: linear-gradient(45deg, rgb(102, 102, 102) 50%, rgba(255, 255, 255, 0) 51%, rgba(255, 255, 255, 0) 100%) !important;
+ /* stylelint-disable-next-line max-line-length */
+ background: linear-gradient(45deg, rgb(102, 102, 102) 50%, rgba(255, 255, 255, 0%) 51%, rgba(255, 255, 255, 0%) 100%) !important;
}
.gm-style-iw button {
- background-image: url(../../images/close.svg) !important;
+ background-image: url("../../images/close.svg") !important;
background-repeat: no-repeat !important;
}
@@ -744,11 +745,11 @@ button > * {
color: #fff;
border: none;
border-radius: 2px;
- background-color: rgba(0, 60, 136, 0.5);
+ background-color: rgba(0, 60, 136, 50%);
}
.ol-layerswitcher:hover {
- background-color: rgba(0, 60, 136, 0.7);
+ background-color: rgba(0, 60, 136, 70%);
}
.ol-layerswitcher label {
diff --git a/helpers/auth.php b/helpers/auth.php
index 9908efa..6762b2f 100644
--- a/helpers/auth.php
+++ b/helpers/auth.php
@@ -17,185 +17,185 @@
* along with this program; if not, see .
*/
- if (!defined('ROOT_DIR')) { define('ROOT_DIR', dirname(__DIR__)); }
- require_once(ROOT_DIR . "/helpers/user.php");
- require_once(ROOT_DIR . "/helpers/utils.php");
- if (!defined('BASE_URL')) { define('BASE_URL', uUtils::getBaseUrl()); }
+if (!defined('ROOT_DIR')) { define('ROOT_DIR', dirname(__DIR__)); }
+require_once(ROOT_DIR . "/helpers/user.php");
+require_once(ROOT_DIR . "/helpers/utils.php");
+if (!defined('BASE_URL')) { define('BASE_URL', uUtils::getBaseUrl()); }
/**
* Authentication
*/
- class uAuth {
+class uAuth {
- /** @var bool Is user authenticated */
- private $isAuthenticated = false;
- /** @var null|uUser */
- public $user;
+ /** @var bool Is user authenticated */
+ private $isAuthenticated = false;
+ /** @var null|uUser */
+ public $user;
- public function __construct() {
- $this->sessionStart();
+ public function __construct() {
+ $this->sessionStart();
- $user = uUser::getFromSession();
- if ($user->isValid) {
- $this->setAuthenticated($user);
- }
+ $user = uUser::getFromSession();
+ if ($user->isValid) {
+ $this->setAuthenticated($user);
}
-
- /**
- * Update user instance stored in session
- */
- public function updateSession() {
- if ($this->isAuthenticated()) {
- $this->user->storeInSession();
- }
- }
-
- /**
- * Is user authenticated
- *
- * @return boolean True if authenticated, false otherwise
- */
- public function isAuthenticated() {
- return $this->isAuthenticated;
- }
-
- /**
- * Is authenticated user admin
- *
- * @return boolean True if admin, false otherwise
- */
- public function isAdmin() {
- return ($this->isAuthenticated && $this->user->isAdmin);
- }
-
- /**
- * Start php session
- *
- * @return void
- */
- private function sessionStart() {
- session_name("ulogger");
- session_start();
- }
-
- /**
- * Terminate php session
- *
- * @return void
- */
- private function sessionEnd() {
- $_SESSION = [];
- if (ini_get("session.use_cookies") && isset($_COOKIE[session_name()])) {
- $params = session_get_cookie_params();
- setcookie(session_name(), '', time() - 42000,
- $params["path"], $params["domain"],
- $params["secure"], $params["httponly"]
- );
- }
- session_destroy();
- }
-
- /**
- * Clean session variables
- *
- * @return void
- */
- private function sessionCleanup() {
- $_SESSION = [];
- }
-
- /**
- * Mark as authenticated, set user
- *
- * @param uUser $user
- * @return void
- */
- private function setAuthenticated($user) {
- $this->isAuthenticated = true;
- $this->user = $user;
- }
-
- /**
- * Check valid pass for given login
- *
- * @param string $login
- * @param string $pass
- * @return boolean True if valid
- */
- public function checkLogin($login, $pass) {
- if (!empty($login) && !empty($pass)) {
- $user = new uUser($login);
- if ($user->isValid && $user->validPassword($pass)) {
- $this->setAuthenticated($user);
- $this->sessionCleanup();
- $user->storeInSession();
- return true;
- }
- }
- return false;
- }
-
- /**
- * Log out with redirect
- *
- * @param string $path URL path (without leading slash)
- * @return void
- */
- public function logOutWithRedirect($path = "") {
- $this->sessionEnd();
- $this->exitWithRedirect($path);
- }
-
- /**
- * Send 401 headers
- *
- * @return void
- */
- public function sendUnauthorizedHeader() {
- header('WWW-Authenticate: OAuth realm="users@ulogger"');
- header('HTTP/1.1 401 Unauthorized', true, 401);
- }
-
- /**
- * Send 401 headers and exit
- *
- * @return void
- */
- public function exitWithUnauthorized() {
- $this->sendUnauthorizedHeader();
- exit();
- }
-
- /**
- * Redirect browser and exit
- *
- * @param string $path Redirect URL path (without leading slash)
- * @return void
- */
- public function exitWithRedirect($path = "") {
- $location = BASE_URL . $path;
- header("Location: $location");
- exit();
- }
-
- /**
- * Check session user has RW access to resource owned by given user
- *
- * @param int $ownerId
- * @return bool True if has access
- */
- public function hasReadWriteAccess($ownerId) {
- return $this->isAuthenticated() && ($this->isAdmin() || $this->user->id === $ownerId);
- }
-
- /**
- * Check session user has RO access to resource owned by given user
- *
- * @param int $ownerId
- * @return bool True if has access
- */
- public function hasReadAccess($ownerId) {
- return $this->hasReadWriteAccess($ownerId) || uConfig::getInstance()->publicTracks;
- }
-
}
+
+ /**
+ * Update user instance stored in session
+ */
+ public function updateSession() {
+ if ($this->isAuthenticated()) {
+ $this->user->storeInSession();
+ }
+ }
+
+ /**
+ * Is user authenticated
+ *
+ * @return boolean True if authenticated, false otherwise
+ */
+ public function isAuthenticated() {
+ return $this->isAuthenticated;
+ }
+
+ /**
+ * Is authenticated user admin
+ *
+ * @return boolean True if admin, false otherwise
+ */
+ public function isAdmin() {
+ return ($this->isAuthenticated && $this->user->isAdmin);
+ }
+
+ /**
+ * Start php session
+ *
+ * @return void
+ */
+ private function sessionStart() {
+ session_name("ulogger");
+ session_start();
+ }
+
+ /**
+ * Terminate php session
+ *
+ * @return void
+ */
+ private function sessionEnd() {
+ $_SESSION = [];
+ if (ini_get("session.use_cookies") && isset($_COOKIE[session_name()])) {
+ $params = session_get_cookie_params();
+ setcookie(session_name(), '', time() - 42000,
+ $params["path"], $params["domain"],
+ $params["secure"], $params["httponly"]
+ );
+ }
+ session_destroy();
+ }
+
+ /**
+ * Clean session variables
+ *
+ * @return void
+ */
+ private function sessionCleanup() {
+ $_SESSION = [];
+ }
+
+ /**
+ * Mark as authenticated, set user
+ *
+ * @param uUser $user
+ * @return void
+ */
+ private function setAuthenticated($user) {
+ $this->isAuthenticated = true;
+ $this->user = $user;
+ }
+
+ /**
+ * Check valid pass for given login
+ *
+ * @param string $login
+ * @param string $pass
+ * @return boolean True if valid
+ */
+ public function checkLogin($login, $pass) {
+ if (!empty($login) && !empty($pass)) {
+ $user = new uUser($login);
+ if ($user->isValid && $user->validPassword($pass)) {
+ $this->setAuthenticated($user);
+ $this->sessionCleanup();
+ $user->storeInSession();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Log out with redirect
+ *
+ * @param string $path URL path (without leading slash)
+ * @return void
+ */
+ public function logOutWithRedirect($path = "") {
+ $this->sessionEnd();
+ $this->exitWithRedirect($path);
+ }
+
+ /**
+ * Send 401 headers
+ *
+ * @return void
+ */
+ public function sendUnauthorizedHeader() {
+ header('WWW-Authenticate: OAuth realm="users@ulogger"');
+ header('HTTP/1.1 401 Unauthorized', true, 401);
+ }
+
+ /**
+ * Send 401 headers and exit
+ *
+ * @return void
+ */
+ public function exitWithUnauthorized() {
+ $this->sendUnauthorizedHeader();
+ exit();
+ }
+
+ /**
+ * Redirect browser and exit
+ *
+ * @param string $path Redirect URL path (without leading slash)
+ * @return void
+ */
+ public function exitWithRedirect($path = "") {
+ $location = BASE_URL . $path;
+ header("Location: $location");
+ exit();
+ }
+
+ /**
+ * Check session user has RW access to resource owned by given user
+ *
+ * @param int $ownerId
+ * @return bool True if has access
+ */
+ public function hasReadWriteAccess($ownerId) {
+ return $this->isAuthenticated() && ($this->isAdmin() || $this->user->id === $ownerId);
+ }
+
+ /**
+ * Check session user has RO access to resource owned by given user
+ *
+ * @param int $ownerId
+ * @return bool True if has access
+ */
+ public function hasReadAccess($ownerId) {
+ return $this->hasReadWriteAccess($ownerId) || uConfig::getInstance()->publicTracks;
+ }
+
+}
diff --git a/helpers/db.php b/helpers/db.php
index cc1bd63..085087d 100644
--- a/helpers/db.php
+++ b/helpers/db.php
@@ -19,302 +19,302 @@
require_once(ROOT_DIR . "/helpers/utils.php");
- /**
- * PDO wrapper
- */
- class uDb extends PDO {
- /**
- * Singleton instance
- *
- * @var uDb Object instance
- */
- protected static $instance;
+/**
+ * PDO wrapper
+ */
+class uDb extends PDO {
+ /**
+ * Singleton instance
+ *
+ * @var uDb Object instance
+ */
+ protected static $instance;
- /**
- * Table names
- *
- * @var array Array of names
- */
- protected static $tables;
+ /**
+ * Table names
+ *
+ * @var array Array of names
+ */
+ protected static $tables;
- /**
- * Database driver name
- *
- * @var string Driver
- */
- protected static $driver;
+ /**
+ * Database driver name
+ *
+ * @var string Driver
+ */
+ protected static $driver;
- /**
- * @var string Database DSN
- */
- private static $dbdsn = "";
- /**
- * @var string Database user
- */
- private static $dbuser = "";
- /**
- * @var string Database pass
- */
- private static $dbpass = "";
- /**
- * @var string Optional table names prefix, eg. "ulogger_"
- */
- private static $dbprefix = "";
+ /**
+ * @var string Database DSN
+ */
+ private static $dbdsn = "";
+ /**
+ * @var string Database user
+ */
+ private static $dbuser = "";
+ /**
+ * @var string Database pass
+ */
+ private static $dbpass = "";
+ /**
+ * @var string Optional table names prefix, eg. "ulogger_"
+ */
+ private static $dbprefix = "";
- /**
- * PDO constuctor
- *
- * @param string $dsn
- * @param string $user
- * @param string $pass
- */
- public function __construct($dsn, $user, $pass) {
- try {
- $options = [
- PDO::ATTR_EMULATE_PREPARES => false, // try to use native prepared statements
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // throw exceptions
- 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) {
- header("HTTP/1.1 503 Service Unavailable");
- die("Database connection error (" . $e->getMessage() . ")");
- }
- }
-
- /**
- * Initialize table names based on config
- */
- private function initTables() {
- self::$tables = [];
- $prefix = preg_replace('/[^a-z0-9_]/i', '', self::$dbprefix);
- self::$tables['positions'] = $prefix . "positions";
- self::$tables['tracks'] = $prefix . "tracks";
- self::$tables['users'] = $prefix . "users";
- self::$tables['config'] = $prefix . "config";
- self::$tables['ol_layers'] = $prefix . "ol_layers";
- }
-
- /**
- * Returns singleton instance
- *
- * @return uDb Singleton instance
- */
- public static function getInstance() {
- if (!self::$instance) {
- self::getConfig();
- self::$instance = new self(self::$dbdsn, self::$dbuser, self::$dbpass);
- }
- return self::$instance;
- }
-
- /**
- * Read database setup from config file
- * @noinspection IssetArgumentExistenceInspection
- * @noinspection PhpIncludeInspection
- */
- private static function getConfig() {
- $configFile = dirname(__DIR__) . "/config.php";
- if (!file_exists($configFile)) {
- header("HTTP/1.1 503 Service Unavailable");
- die("Missing config.php file!");
- }
- include($configFile);
- if (isset($dbdsn)) {
- self::$dbdsn = self::normalizeDsn($dbdsn);
- }
- if (isset($dbuser)) {
- self::$dbuser = $dbuser;
- }
- if (isset($dbpass)) {
- self::$dbpass = $dbpass;
- }
- if (isset($dbprefix)) {
- self::$dbprefix = $dbprefix;
- }
- }
-
- /**
- * Get full table name including prefix
- *
- * @param string $name Name
- * @return string Full table name
- */
- public function table($name) {
- return self::$tables[$name];
- }
-
- /**
- * Returns function name for getting date-time column value as unix timestamp
- * @param string $column
- * @return string
- */
- public function unix_timestamp($column) {
- switch (self::$driver) {
- default:
- case "mysql":
- return "UNIX_TIMESTAMP($column)";
- break;
- case "pgsql":
- return "EXTRACT(EPOCH FROM $column::TIMESTAMP WITH TIME ZONE)";
- break;
- case "sqlite":
- return "STRFTIME('%s', $column)";
- break;
- }
- }
-
- /**
- * Returns placeholder for LOB data types
- * @return string
- */
- public function lobPlaceholder() {
- switch (self::$driver) {
- default:
- case "mysql":
- case "sqlite":
- return "?";
- break;
- case "pgsql":
- return "?::bytea";
- break;
- }
- }
-
- /**
- * Returns construct for getting LOB as string
- * @param string $column Column name
- * @return string
- */
- public function from_lob($column) {
- switch (self::$driver) {
- default:
- case "mysql":
- case "sqlite":
- return $column;
- break;
- case "pgsql":
- return "encode($column, 'escape') AS $column";
- break;
- }
- }
-
- /**
- * Returns function name for getting date-time column value as 'YYYY-MM-DD hh:mm:ss'
- * @param string $column
- * @return string
- */
- public function from_unixtime($column) {
- switch (self::$driver) {
- default:
- case "mysql":
- return "FROM_UNIXTIME($column)";
- break;
- case "pgsql":
- return "TO_TIMESTAMP($column)";
- break;
- case "sqlite":
- return "DATETIME($column, 'unixepoch')";
- break;
- }
- }
-
- /**
- * Replace into
- * Note: requires PostgreSQL >= 9.5
- * @param string $table Table name (without prefix)
- * @param string[] $columns Column names
- * @param string[][] $values Values [ [ value1, value2 ], ... ]
- * @param string $key Unique column
- * @param string $update Updated column
- * @return string
- */
- public function insertOrReplace($table, $columns, $values, $key, $update) {
- $cols = implode(", ", $columns);
- $rows = [];
- foreach ($values as $row) {
- $rows[] = "(" . implode(", ", $row) . ")";
- }
- $vals = implode(", ", $rows);
- switch (self::$driver) {
- default:
- case "mysql":
- return "INSERT INTO {$this->table($table)} ($cols)
- VALUES $vals
- ON DUPLICATE KEY UPDATE $update = VALUES($update)";
- break;
- case "pgsql":
- return "INSERT INTO {$this->table($table)} ($cols)
- VALUES $vals
- ON CONFLICT ($key) DO UPDATE SET $update = EXCLUDED.$update";
- break;
- case "sqlite":
- return "REPLACE INTO {$this->table($table)} ($cols)
- VALUES $vals";
- break;
- }
- }
-
- /**
- * Set character set
- * @param string $charset
- */
- private function setCharset($charset) {
- if (self::$driver === "pgsql" || self::$driver === "mysql") {
- $this->exec("SET NAMES '$charset'");
- }
- }
-
- /**
- * Extract database name from DSN
- * @param string $dsn
- * @return string Empty string if not found
- */
- public static function getDbName($dsn) {
- $name = "";
- if (strpos($dsn, ":") !== false) {
- list($scheme, $dsnWithoutScheme) = explode(":", $dsn, 2);
- switch ($scheme) {
- case "sqlite":
- case "sqlite2":
- case "sqlite3":
- $pattern = "/(.+)/";
- break;
- case "pgsql":
- $pattern = "/dbname=([^; ]+)/";
- break;
- default:
- $pattern = "/dbname=([^;]+)/";
- break;
- }
- $result = preg_match($pattern, $dsnWithoutScheme, $matches);
- if ($result === 1) {
- $name = $matches[1];
- }
- }
- return $name;
- }
-
- /**
- * Normalize DSN.
- * Make sure sqlite DSN file path is absolute
- * @param $dsn string DSN
- * @return string Normalized DSN
- */
- public static function normalizeDsn($dsn) {
- if (stripos($dsn, "sqlite") !== 0) {
- return $dsn;
- }
- $arr = explode(":", $dsn, 2);
- if (count($arr) < 2 || empty($arr[1]) || uUtils::isAbsolutePath($arr[1])) {
- return $dsn;
- }
- $scheme = $arr[0];
- $path = dirname(__DIR__) . DIRECTORY_SEPARATOR . $arr[1];
- return $scheme . ":" . realpath(dirname($path)) . DIRECTORY_SEPARATOR . basename(($path));
+ /**
+ * PDO constuctor
+ *
+ * @param string $dsn
+ * @param string $user
+ * @param string $pass
+ */
+ public function __construct($dsn, $user, $pass) {
+ try {
+ $options = [
+ PDO::ATTR_EMULATE_PREPARES => false, // try to use native prepared statements
+ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // throw exceptions
+ 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) {
+ header("HTTP/1.1 503 Service Unavailable");
+ die("Database connection error (" . $e->getMessage() . ")");
}
}
+
+ /**
+ * Initialize table names based on config
+ */
+ private function initTables() {
+ self::$tables = [];
+ $prefix = preg_replace('/[^a-z0-9_]/i', '', self::$dbprefix);
+ self::$tables['positions'] = $prefix . "positions";
+ self::$tables['tracks'] = $prefix . "tracks";
+ self::$tables['users'] = $prefix . "users";
+ self::$tables['config'] = $prefix . "config";
+ self::$tables['ol_layers'] = $prefix . "ol_layers";
+ }
+
+ /**
+ * Returns singleton instance
+ *
+ * @return uDb Singleton instance
+ */
+ public static function getInstance() {
+ if (!self::$instance) {
+ self::getConfig();
+ self::$instance = new self(self::$dbdsn, self::$dbuser, self::$dbpass);
+ }
+ return self::$instance;
+ }
+
+ /**
+ * Read database setup from config file
+ * @noinspection IssetArgumentExistenceInspection
+ * @noinspection PhpIncludeInspection
+ */
+ private static function getConfig() {
+ $configFile = dirname(__DIR__) . "/config.php";
+ if (!file_exists($configFile)) {
+ header("HTTP/1.1 503 Service Unavailable");
+ die("Missing config.php file!");
+ }
+ include($configFile);
+ if (isset($dbdsn)) {
+ self::$dbdsn = self::normalizeDsn($dbdsn);
+ }
+ if (isset($dbuser)) {
+ self::$dbuser = $dbuser;
+ }
+ if (isset($dbpass)) {
+ self::$dbpass = $dbpass;
+ }
+ if (isset($dbprefix)) {
+ self::$dbprefix = $dbprefix;
+ }
+ }
+
+ /**
+ * Get full table name including prefix
+ *
+ * @param string $name Name
+ * @return string Full table name
+ */
+ public function table($name) {
+ return self::$tables[$name];
+ }
+
+ /**
+ * Returns function name for getting date-time column value as unix timestamp
+ * @param string $column
+ * @return string
+ */
+ public function unix_timestamp($column) {
+ switch (self::$driver) {
+ default:
+ case "mysql":
+ return "UNIX_TIMESTAMP($column)";
+ break;
+ case "pgsql":
+ return "EXTRACT(EPOCH FROM $column::TIMESTAMP WITH TIME ZONE)";
+ break;
+ case "sqlite":
+ return "STRFTIME('%s', $column)";
+ break;
+ }
+ }
+
+ /**
+ * Returns placeholder for LOB data types
+ * @return string
+ */
+ public function lobPlaceholder() {
+ switch (self::$driver) {
+ default:
+ case "mysql":
+ case "sqlite":
+ return "?";
+ break;
+ case "pgsql":
+ return "?::bytea";
+ break;
+ }
+ }
+
+ /**
+ * Returns construct for getting LOB as string
+ * @param string $column Column name
+ * @return string
+ */
+ public function from_lob($column) {
+ switch (self::$driver) {
+ default:
+ case "mysql":
+ case "sqlite":
+ return $column;
+ break;
+ case "pgsql":
+ return "encode($column, 'escape') AS $column";
+ break;
+ }
+ }
+
+ /**
+ * Returns function name for getting date-time column value as 'YYYY-MM-DD hh:mm:ss'
+ * @param string $column
+ * @return string
+ */
+ public function from_unixtime($column) {
+ switch (self::$driver) {
+ default:
+ case "mysql":
+ return "FROM_UNIXTIME($column)";
+ break;
+ case "pgsql":
+ return "TO_TIMESTAMP($column)";
+ break;
+ case "sqlite":
+ return "DATETIME($column, 'unixepoch')";
+ break;
+ }
+ }
+
+ /**
+ * Replace into
+ * Note: requires PostgreSQL >= 9.5
+ * @param string $table Table name (without prefix)
+ * @param string[] $columns Column names
+ * @param string[][] $values Values [ [ value1, value2 ], ... ]
+ * @param string $key Unique column
+ * @param string $update Updated column
+ * @return string
+ */
+ public function insertOrReplace($table, $columns, $values, $key, $update) {
+ $cols = implode(", ", $columns);
+ $rows = [];
+ foreach ($values as $row) {
+ $rows[] = "(" . implode(", ", $row) . ")";
+ }
+ $vals = implode(", ", $rows);
+ switch (self::$driver) {
+ default:
+ case "mysql":
+ return "INSERT INTO {$this->table($table)} ($cols)
+ VALUES $vals
+ ON DUPLICATE KEY UPDATE $update = VALUES($update)";
+ break;
+ case "pgsql":
+ return "INSERT INTO {$this->table($table)} ($cols)
+ VALUES $vals
+ ON CONFLICT ($key) DO UPDATE SET $update = EXCLUDED.$update";
+ break;
+ case "sqlite":
+ return "REPLACE INTO {$this->table($table)} ($cols)
+ VALUES $vals";
+ break;
+ }
+ }
+
+ /**
+ * Set character set
+ * @param string $charset
+ */
+ private function setCharset($charset) {
+ if (self::$driver === "pgsql" || self::$driver === "mysql") {
+ $this->exec("SET NAMES '$charset'");
+ }
+ }
+
+ /**
+ * Extract database name from DSN
+ * @param string $dsn
+ * @return string Empty string if not found
+ */
+ public static function getDbName($dsn) {
+ $name = "";
+ if ($dsn && strpos($dsn, ":") !== false) {
+ list($scheme, $dsnWithoutScheme) = explode(":", $dsn, 2);
+ switch ($scheme) {
+ case "sqlite":
+ case "sqlite2":
+ case "sqlite3":
+ $pattern = "/(.+)/";
+ break;
+ case "pgsql":
+ $pattern = "/dbname=([^; ]+)/";
+ break;
+ default:
+ $pattern = "/dbname=([^;]+)/";
+ break;
+ }
+ $result = preg_match($pattern, $dsnWithoutScheme, $matches);
+ if ($result === 1) {
+ $name = $matches[1];
+ }
+ }
+ return $name;
+ }
+
+ /**
+ * Normalize DSN.
+ * Make sure sqlite DSN file path is absolute
+ * @param string $dsn DSN
+ * @return string Normalized DSN
+ */
+ public static function normalizeDsn($dsn) {
+ if (stripos($dsn, "sqlite") !== 0) {
+ return $dsn;
+ }
+ $arr = explode(":", $dsn, 2);
+ if (count($arr) < 2 || empty($arr[1]) || uUtils::isAbsolutePath($arr[1])) {
+ return $dsn;
+ }
+ $scheme = $arr[0];
+ $path = dirname(__DIR__) . DIRECTORY_SEPARATOR . $arr[1];
+ return $scheme . ":" . realpath(dirname($path)) . DIRECTORY_SEPARATOR . basename(($path));
+ }
+}
?>
diff --git a/helpers/lang.php b/helpers/lang.php
index d352397..b6e14c1 100644
--- a/helpers/lang.php
+++ b/helpers/lang.php
@@ -17,100 +17,100 @@
* along with this program; if not, see .
*/
- require_once(ROOT_DIR . "/helpers/config.php");
+require_once(ROOT_DIR . "/helpers/config.php");
+
+/**
+ * Localization
+ */
+class uLang {
/**
- * Localization
- */
- class uLang {
+ * Available languages
+ *
+ * @var array
+ */
+ private static $languages = [
+ "ca" => "Català",
+ "cs" => "Čeština",
+ "de" => "Deutsch",
+ "el" => "Ελληνικά",
+ "en" => "English",
+ "es" => "Español",
+ "eu" => "Euskera",
+ "fr" => "Français",
+ "it" => "Italiano",
+ "pl" => "Polski",
+ "ru" => "Русский",
+ "sk" => "Slovenčina"
+ ];
- /**
- * Available languages
- *
- * @var array
- */
- private static $languages = [
- "ca" => "Català",
- "cs" => "Čeština",
- "de" => "Deutsch",
- "el" => "Ελληνικά",
- "en" => "English",
- "es" => "Español",
- "eu" => "Euskera",
- "fr" => "Français",
- "it" => "Italiano",
- "pl" => "Polski",
- "ru" => "Русский",
- "sk" => "Slovenčina"
- ];
+ /**
+ * Application strings
+ * Array of key => translation pairs
+ *
+ * @var array
+ */
+ private $strings;
+ /**
+ * Setup script strings
+ * Array of key => translation pairs
+ *
+ * @var array
+ */
+ private $setupStrings;
- /**
- * Application strings
- * Array of key => translation pairs
- *
- * @var array
- */
- private $strings;
- /**
- * Setup script strings
- * Array of key => translation pairs
- *
- * @var array
- */
- private $setupStrings;
+ /**
+ * Constructor
+ *
+ * @param uConfig $config Config
+ */
+ public function __construct($config) {
+ $language = $config->lang;
+ $lang = [];
+ $langSetup = [];
+ // always load en base
+ require(ROOT_DIR . "/lang/en.php");
- /**
- * Constructor
- *
- * @param uConfig $config Config
- */
- public function __construct($config) {
- $language = $config->lang;
- $lang = [];
- $langSetup = [];
- // always load en base
- require(ROOT_DIR . "/lang/en.php");
-
- // override with translated strings if needed
- // missing strings will be displayed in English
- if ($language !== "en" && array_key_exists($language, self::$languages)) {
- require(ROOT_DIR . "/lang/$language.php");
- }
-
- $this->strings = $lang;
- $this->setupStrings = $langSetup;
- }
-
- /**
- * Get supported languages array
- * Language code => Native language name
- *
- * @return array
- */
- public static function getLanguages() {
- return self::$languages;
- }
-
- /**
- * Get translated strings array
- * Key => translation string
- *
- * @return array
- */
- public function getStrings() {
- return $this->strings;
- }
-
- /**
- * Get translated strings array for setup script
- * Key => translation string
- *
- * @return array
- */
- public function getSetupStrings() {
- return $this->setupStrings;
+ // override with translated strings if needed
+ // missing strings will be displayed in English
+ if ($language !== "en" && array_key_exists($language, self::$languages)) {
+ require(ROOT_DIR . "/lang/$language.php");
}
+ $this->strings = $lang;
+ $this->setupStrings = $langSetup;
}
- ?>
+ /**
+ * Get supported languages array
+ * Language code => Native language name
+ *
+ * @return array
+ */
+ public static function getLanguages() {
+ return self::$languages;
+ }
+
+ /**
+ * Get translated strings array
+ * Key => translation string
+ *
+ * @return array
+ */
+ public function getStrings() {
+ return $this->strings;
+ }
+
+ /**
+ * Get translated strings array for setup script
+ * Key => translation string
+ *
+ * @return array
+ */
+ public function getSetupStrings() {
+ return $this->setupStrings;
+ }
+
+}
+
+?>
diff --git a/helpers/position.php b/helpers/position.php
index 96764ec..86f8ce9 100644
--- a/helpers/position.php
+++ b/helpers/position.php
@@ -21,485 +21,485 @@ require_once(ROOT_DIR . "/helpers/db.php");
require_once(ROOT_DIR . "/helpers/track.php");
require_once(ROOT_DIR . "/helpers/upload.php");
- /**
- * Positions handling
- */
- class uPosition {
- /** @param int Position id */
- public $id;
- /** @param int Unix time stamp */
- public $timestamp;
- /** @param int User id */
- public $userId;
- /** @param String User login */
- public $userLogin;
- /** @param int Track id */
- public $trackId;
- /** @param String Track name */
- public $trackName;
- /** @param double Latitude */
- public $latitude;
- /** @param double Longitude */
- public $longitude;
- /** @param double Altitude */
- public $altitude;
- /** @param double Speed */
- public $speed;
- /** @param double Bearing */
- public $bearing;
- /** @param int Accuracy */
- public $accuracy;
- /** @param String Provider */
- public $provider;
- /** @param String Comment */
- public $comment;
- /** @param String Image path */
- public $image;
+/**
+ * Positions handling
+ */
+class uPosition {
+ /** @param int Position id */
+ public $id;
+ /** @param int Unix time stamp */
+ public $timestamp;
+ /** @param int User id */
+ public $userId;
+ /** @param String User login */
+ public $userLogin;
+ /** @param int Track id */
+ public $trackId;
+ /** @param String Track name */
+ public $trackName;
+ /** @param double Latitude */
+ public $latitude;
+ /** @param double Longitude */
+ public $longitude;
+ /** @param double Altitude */
+ public $altitude;
+ /** @param double Speed */
+ public $speed;
+ /** @param double Bearing */
+ public $bearing;
+ /** @param int Accuracy */
+ public $accuracy;
+ /** @param String Provider */
+ public $provider;
+ /** @param String Comment */
+ public $comment;
+ /** @param String Image path */
+ public $image;
- public $isValid = false;
+ public $isValid = false;
- /**
- * Constructor
- * @param integer $positionId Position id
- */
- public function __construct($positionId = NULL) {
+ /**
+ * Constructor
+ * @param integer $positionId Position id
+ */
+ public function __construct($positionId = null) {
- if (!empty($positionId)) {
- $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
- p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
- p.comment, p.image, u.login, t.name
- FROM " . self::db()->table('positions') . " p
- LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
- LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
- WHERE p.id = ? LIMIT 1";
- $params = [ $positionId ];
- try {
- $this->loadWithQuery($query, $params);
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- }
-
- /**
- * Get db instance
- *
- * @return uDb instance
- */
- private static function db() {
- return uDb::getInstance();
- }
-
- /**
- * Has image
- *
- * @return bool True if has image
- */
- public function hasImage() {
- return !empty($this->image);
- }
-
- /**
- * Add position
- *
- * @param int $userId
- * @param int $trackId
- * @param int $timestamp Unix time stamp
- * @param double $lat
- * @param double $lon
- * @param double $altitude Optional
- * @param double $speed Optional
- * @param double $bearing Optional
- * @param int $accuracy Optional
- * @param string $provider Optional
- * @param string $comment Optional
- * @param int $image Optional
- * @return int|bool New position id in database, false on error
- */
- public static function add($userId, $trackId, $timestamp, $lat, $lon,
- $altitude = NULL, $speed = NULL, $bearing = NULL, $accuracy = NULL,
- $provider = NULL, $comment = NULL, $image = NULL) {
- $positionId = false;
- if (is_numeric($lat) && is_numeric($lon) && is_numeric($timestamp) && is_numeric($userId) && is_numeric($trackId)) {
- $track = new uTrack($trackId);
- if ($track->isValid && $track->userId === $userId) {
- try {
- $table = self::db()->table('positions');
- $query = "INSERT INTO $table
- (user_id, track_id,
- time, latitude, longitude, altitude, speed, bearing, accuracy, provider, comment, image)
- VALUES (?, ?, " . self::db()->from_unixtime('?') . ", ?, ?, ?, ?, ?, ?, ?, ?, ?)";
- $stmt = self::db()->prepare($query);
- $params = [ $userId, $trackId,
- $timestamp, $lat, $lon, $altitude, $speed, $bearing, $accuracy, $provider, $comment, $image ];
- $stmt->execute($params);
- $positionId = (int) self::db()->lastInsertId("${table}_id_seq");
- } catch (PDOException $e) {
- // TODO: handle error
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- }
- return $positionId;
- }
-
- /**
- * Save position to database
- *
- * @return bool True if success, false otherwise
- */
- public function update() {
- $ret = false;
- if ($this->isValid) {
- try {
- $query = "UPDATE " . self::db()->table('positions') . " SET
- time = " . self::db()->from_unixtime('?') . ", user_id = ?, track_id = ?, latitude = ?, longitude = ?, altitude = ?,
- speed = ?, bearing = ?, accuracy = ?, provider = ?, comment = ?, image = ? WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $params = [
- $this->timestamp,
- $this->userId,
- $this->trackId,
- $this->latitude,
- $this->longitude,
- $this->altitude,
- $this->speed,
- $this->bearing,
- $this->accuracy,
- $this->provider,
- $this->comment,
- $this->image,
- $this->id
- ];
- $stmt->execute($params);
- $ret = true;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Delete positions
- *
- * @return bool True if success, false otherwise
- */
- public function delete() {
- $ret = false;
- if ($this->isValid) {
- try {
- $query = "DELETE FROM " . self::db()->table('positions') . " WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $this->id ]);
- $this->removeImage();
- $ret = true;
- $this->id = NULL;
- $this->isValid = false;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Delete all user's positions, optionally limit to given track
- *
- * @param int $userId User id
- * @param int $trackId Optional track id
- * @return bool True if success, false otherwise
- */
- public static function deleteAll($userId, $trackId = NULL) {
- $ret = false;
- if (!empty($userId)) {
- $args = [];
- $where = "WHERE user_id = ?";
- $args[] = $userId;
- if (!empty($trackId)) {
- $where .= " AND track_id = ?";
- $args[] = $trackId;
- }
- self::removeImages($userId, $trackId);
- try {
- $query = "DELETE FROM " . self::db()->table('positions') . " $where";
- $stmt = self::db()->prepare($query);
- $stmt->execute($args);
- $ret = true;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Get last position data from database
- * (for given user if specified)
- *
- * @param int $userId Optional user id
- * @return uPosition Position
- */
- public static function getLast($userId = NULL) {
- if (!empty($userId)) {
- $where = "WHERE p.user_id = ?";
- $params = [ $userId ];
- } else {
- $where = "";
- $params = NULL;
- }
+ if (!empty($positionId)) {
$query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
p.comment, p.image, u.login, t.name
FROM " . self::db()->table('positions') . " p
LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
- $where
- ORDER BY p.time DESC, p.id DESC LIMIT 1";
- $position = new uPosition();
+ WHERE p.id = ? LIMIT 1";
+ $params = [ $positionId ];
try {
- $position->loadWithQuery($query, $params);
+ $this->loadWithQuery($query, $params);
} catch (PDOException $e) {
// TODO: handle exception
syslog(LOG_ERR, $e->getMessage());
}
- return $position;
- }
-
- /**
- * Get last positions for all users
- *
- * @return array|bool Array of uPosition positions, false on error
- */
- public static function getLastAllUsers() {
- $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
- p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
- p.comment, p.image, u.login, t.name
- FROM " . self::db()->table('positions') . " p
- LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
- LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
- WHERE p.id = (
- SELECT p2.id FROM " . self::db()->table('positions') . " p2
- WHERE p2.user_id = p.user_id
- ORDER BY p2.time DESC, p2.id DESC
- LIMIT 1
- )";
- $positionsArr = [];
- try {
- $result = self::db()->query($query);
- while ($row = $result->fetch()) {
- $positionsArr[] = self::rowToObject($row);
- }
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- $positionsArr = false;
- }
- return $positionsArr;
- }
-
- /**
- * Get array of all positions
- *
- * @param int $userId Optional limit to given user id
- * @param int $trackId Optional limit to given track id
- * @param int $afterId Optional limit to positions with id greater then given id
- * @param array $rules Optional rules
- * @return uPosition[]|bool Array of uPosition positions, false on error
- */
- public static function getAll($userId = NULL, $trackId = NULL, $afterId = NULL, $rules = []) {
- if (!empty($userId)) {
- $rules[] = "p.user_id = " . self::db()->quote($userId);
- }
- if (!empty($trackId)) {
- $rules[] = "p.track_id = " . self::db()->quote($trackId);
- }
- if (!empty($afterId)) {
- $rules[] = "p.id > " . self::db()->quote($afterId);
- }
- if (!empty($rules)) {
- $where = "WHERE " . implode(" AND ", $rules);
- } else {
- $where = "";
- }
- $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
- p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
- p.comment, p.image, u.login, t.name
- FROM " . self::db()->table('positions') . " p
- LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
- LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
- $where
- ORDER BY p.time, p.id";
- $positionsArr = [];
- try {
- $result = self::db()->query($query);
- while ($row = $result->fetch()) {
- $positionsArr[] = self::rowToObject($row);
- }
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- $positionsArr = false;
- }
- return $positionsArr;
- }
-
- /**
- * Get array of all positions with image
- *
- * @param int $userId Optional limit to given user id
- * @param int $trackId Optional limit to given track id
- * @param int $afterId Optional limit to positions with id greater then given id
- * @param array $rules Optional rules
- * @return uPosition[]|bool Array of uPosition positions, false on error
- */
- public static function getAllWithImage($userId = NULL, $trackId = NULL, $afterId = NULL, $rules = []) {
- $rules[] = "p.image IS NOT NULL";
- return self::getAll($userId, $trackId, $afterId, $rules);
- }
-
- /**
- * Delete all user's uploads, optionally limit to given track
- *
- * @param int $userId User id
- * @param int $trackId Optional track id
- * @return bool True if success, false otherwise
- */
- public static function removeImages($userId, $trackId = NULL) {
- if (($positions = self::getAllWithImage($userId, $trackId)) !== false) {
- foreach ($positions as $position) {
- try {
- $position->removeImage();
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * Add uploaded image
- * @param array $imageMeta File metadata array
- */
- public function setImage($imageMeta) {
- if (!empty($imageMeta)) {
- if ($this->hasImage()) {
- $this->removeImage();
- }
- $this->image = uUpload::add($imageMeta, $this->trackId);
- $query = "UPDATE " . self::db()->table('positions') . "
- SET image = ? WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $this->image, $this->id ]);
- }
- }
-
- /**
- * Delete image
- */
- public function removeImage() {
- if ($this->hasImage()) {
- $query = "UPDATE " . self::db()->table('positions') . "
- SET image = NULL WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $this->id ]);
- // ignore unlink errors
- uUpload::delete($this->image);
- $this->image = null;
- }
- }
-
- /**
- * 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);
- $lat2 = deg2rad($target->latitude);
- $lon2 = deg2rad($target->longitude);
- $latD = $lat2 - $lat1;
- $lonD = $lon2 - $lon1;
- $bearing = 2 * asin(sqrt((sin($latD / 2) ** 2) + cos($lat1) * cos($lat2) * (sin($lonD / 2) ** 2)));
- return $bearing * 6371000;
- }
-
- /**
- * Calculate time elapsed since target point
- *
- * @param uPosition $target Target position
- * @return int Number of seconds
- */
- public function secondsTo($target) {
- return $this->timestamp - $target->timestamp;
- }
-
- /**
- * Convert database row to uPosition
- *
- * @param array $row Row
- * @return uPosition Position
- */
- private static function rowToObject($row) {
- $position = new uPosition();
- $position->id = (int) $row['id'];
- $position->timestamp = (int) $row['tstamp'];
- $position->userId = (int) $row['user_id'];
- $position->userLogin = $row['login'];
- $position->trackId = (int) $row['track_id'];
- $position->trackName = $row['name'];
- $position->latitude = (double) $row['latitude'];
- $position->longitude = (double) $row['longitude'];
- $position->altitude = (double) $row['altitude'];
- $position->speed = (double) $row['speed'];
- $position->bearing = (double) $row['bearing'];
- $position->accuracy = (int) $row['accuracy'];
- $position->provider = $row['provider'];
- $position->comment = $row['comment'];
- $position->image = $row['image'];
- $position->isValid = true;
- return $position;
- }
-
- /**
- * Fill class properties with database query result
- *
- * @param string $query Query
- * @param array|null $params Optional array of bind parameters
- * @throws PDOException
- */
- private function loadWithQuery($query, $params = NULL) {
- $stmt = self::db()->prepare($query);
- $stmt->execute($params);
-
- $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
- $stmt->bindColumn('tstamp', $this->timestamp, PDO::PARAM_INT);
- $stmt->bindColumn('user_id', $this->userId, PDO::PARAM_INT);
- $stmt->bindColumn('track_id', $this->trackId, PDO::PARAM_INT);
- $stmt->bindColumn('latitude', $this->latitude);
- $stmt->bindColumn('longitude', $this->longitude);
- $stmt->bindColumn('altitude', $this->altitude);
- $stmt->bindColumn('speed', $this->speed);
- $stmt->bindColumn('bearing', $this->bearing);
- $stmt->bindColumn('accuracy', $this->accuracy, PDO::PARAM_INT);
- $stmt->bindColumn('provider', $this->provider);
- $stmt->bindColumn('comment', $this->comment);
- $stmt->bindColumn('image', $this->image);
- $stmt->bindColumn('login', $this->userLogin);
- $stmt->bindColumn('name', $this->trackName);
- if ($stmt->fetch(PDO::FETCH_BOUND)) {
- $this->isValid = true;
- }
}
}
+ /**
+ * Get db instance
+ *
+ * @return uDb instance
+ */
+ private static function db() {
+ return uDb::getInstance();
+ }
+
+ /**
+ * Has image
+ *
+ * @return bool True if has image
+ */
+ public function hasImage() {
+ return !empty($this->image);
+ }
+
+ /**
+ * Add position
+ *
+ * @param int $userId
+ * @param int $trackId
+ * @param int $timestamp Unix time stamp
+ * @param double $lat
+ * @param double $lon
+ * @param double $altitude Optional
+ * @param double $speed Optional
+ * @param double $bearing Optional
+ * @param int $accuracy Optional
+ * @param string $provider Optional
+ * @param string $comment Optional
+ * @param int $image Optional
+ * @return int|bool New position id in database, false on error
+ */
+ public static function add($userId, $trackId, $timestamp, $lat, $lon,
+ $altitude = null, $speed = null, $bearing = null, $accuracy = null,
+ $provider = null, $comment = null, $image = null) {
+ $positionId = false;
+ if (is_numeric($lat) && is_numeric($lon) && is_numeric($timestamp) && is_numeric($userId) && is_numeric($trackId)) {
+ $track = new uTrack($trackId);
+ if ($track->isValid && $track->userId === $userId) {
+ try {
+ $table = self::db()->table('positions');
+ $query = "INSERT INTO $table
+ (user_id, track_id,
+ time, latitude, longitude, altitude, speed, bearing, accuracy, provider, comment, image)
+ VALUES (?, ?, " . self::db()->from_unixtime('?') . ", ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ $stmt = self::db()->prepare($query);
+ $params = [ $userId, $trackId,
+ $timestamp, $lat, $lon, $altitude, $speed, $bearing, $accuracy, $provider, $comment, $image ];
+ $stmt->execute($params);
+ $positionId = (int) self::db()->lastInsertId("${table}_id_seq");
+ } catch (PDOException $e) {
+ // TODO: handle error
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ }
+ return $positionId;
+ }
+
+ /**
+ * Save position to database
+ *
+ * @return bool True if success, false otherwise
+ */
+ public function update() {
+ $ret = false;
+ if ($this->isValid) {
+ try {
+ $query = "UPDATE " . self::db()->table('positions') . " SET
+ time = " . self::db()->from_unixtime('?') . ", user_id = ?, track_id = ?, latitude = ?, longitude = ?, altitude = ?,
+ speed = ?, bearing = ?, accuracy = ?, provider = ?, comment = ?, image = ? WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $params = [
+ $this->timestamp,
+ $this->userId,
+ $this->trackId,
+ $this->latitude,
+ $this->longitude,
+ $this->altitude,
+ $this->speed,
+ $this->bearing,
+ $this->accuracy,
+ $this->provider,
+ $this->comment,
+ $this->image,
+ $this->id
+ ];
+ $stmt->execute($params);
+ $ret = true;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Delete positions
+ *
+ * @return bool True if success, false otherwise
+ */
+ public function delete() {
+ $ret = false;
+ if ($this->isValid) {
+ try {
+ $query = "DELETE FROM " . self::db()->table('positions') . " WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $this->id ]);
+ $this->removeImage();
+ $ret = true;
+ $this->id = null;
+ $this->isValid = false;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Delete all user's positions, optionally limit to given track
+ *
+ * @param int $userId User id
+ * @param int $trackId Optional track id
+ * @return bool True if success, false otherwise
+ */
+ public static function deleteAll($userId, $trackId = null) {
+ $ret = false;
+ if (!empty($userId)) {
+ $args = [];
+ $where = "WHERE user_id = ?";
+ $args[] = $userId;
+ if (!empty($trackId)) {
+ $where .= " AND track_id = ?";
+ $args[] = $trackId;
+ }
+ self::removeImages($userId, $trackId);
+ try {
+ $query = "DELETE FROM " . self::db()->table('positions') . " $where";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute($args);
+ $ret = true;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Get last position data from database
+ * (for given user if specified)
+ *
+ * @param int $userId Optional user id
+ * @return uPosition Position
+ */
+ public static function getLast($userId = null) {
+ if (!empty($userId)) {
+ $where = "WHERE p.user_id = ?";
+ $params = [ $userId ];
+ } else {
+ $where = "";
+ $params = null;
+ }
+ $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
+ p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
+ p.comment, p.image, u.login, t.name
+ FROM " . self::db()->table('positions') . " p
+ LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
+ LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
+ $where
+ ORDER BY p.time DESC, p.id DESC LIMIT 1";
+ $position = new uPosition();
+ try {
+ $position->loadWithQuery($query, $params);
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ return $position;
+ }
+
+ /**
+ * Get last positions for all users
+ *
+ * @return array|bool Array of uPosition positions, false on error
+ */
+ public static function getLastAllUsers() {
+ $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
+ p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
+ p.comment, p.image, u.login, t.name
+ FROM " . self::db()->table('positions') . " p
+ LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
+ LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
+ WHERE p.id = (
+ SELECT p2.id FROM " . self::db()->table('positions') . " p2
+ WHERE p2.user_id = p.user_id
+ ORDER BY p2.time DESC, p2.id DESC
+ LIMIT 1
+ )";
+ $positionsArr = [];
+ try {
+ $result = self::db()->query($query);
+ while ($row = $result->fetch()) {
+ $positionsArr[] = self::rowToObject($row);
+ }
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ $positionsArr = false;
+ }
+ return $positionsArr;
+ }
+
+ /**
+ * Get array of all positions
+ *
+ * @param int $userId Optional limit to given user id
+ * @param int $trackId Optional limit to given track id
+ * @param int $afterId Optional limit to positions with id greater then given id
+ * @param array $rules Optional rules
+ * @return uPosition[]|bool Array of uPosition positions, false on error
+ */
+ public static function getAll($userId = null, $trackId = null, $afterId = null, $rules = []) {
+ if (!empty($userId)) {
+ $rules[] = "p.user_id = " . self::db()->quote($userId);
+ }
+ if (!empty($trackId)) {
+ $rules[] = "p.track_id = " . self::db()->quote($trackId);
+ }
+ if (!empty($afterId)) {
+ $rules[] = "p.id > " . self::db()->quote($afterId);
+ }
+ if (!empty($rules)) {
+ $where = "WHERE " . implode(" AND ", $rules);
+ } else {
+ $where = "";
+ }
+ $query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
+ p.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
+ p.comment, p.image, u.login, t.name
+ FROM " . self::db()->table('positions') . " p
+ LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
+ LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
+ $where
+ ORDER BY p.time, p.id";
+ $positionsArr = [];
+ try {
+ $result = self::db()->query($query);
+ while ($row = $result->fetch()) {
+ $positionsArr[] = self::rowToObject($row);
+ }
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ $positionsArr = false;
+ }
+ return $positionsArr;
+ }
+
+ /**
+ * Get array of all positions with image
+ *
+ * @param int $userId Optional limit to given user id
+ * @param int $trackId Optional limit to given track id
+ * @param int $afterId Optional limit to positions with id greater then given id
+ * @param array $rules Optional rules
+ * @return uPosition[]|bool Array of uPosition positions, false on error
+ */
+ public static function getAllWithImage($userId = null, $trackId = null, $afterId = null, $rules = []) {
+ $rules[] = "p.image IS NOT NULL";
+ return self::getAll($userId, $trackId, $afterId, $rules);
+ }
+
+ /**
+ * Delete all user's uploads, optionally limit to given track
+ *
+ * @param int $userId User id
+ * @param int $trackId Optional track id
+ * @return bool True if success, false otherwise
+ */
+ public static function removeImages($userId, $trackId = null) {
+ if (($positions = self::getAllWithImage($userId, $trackId)) !== false) {
+ foreach ($positions as $position) {
+ try {
+ $position->removeImage();
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Add uploaded image
+ * @param array $imageMeta File metadata array
+ */
+ public function setImage($imageMeta) {
+ if (!empty($imageMeta)) {
+ if ($this->hasImage()) {
+ $this->removeImage();
+ }
+ $this->image = uUpload::add($imageMeta, $this->trackId);
+ $query = "UPDATE " . self::db()->table('positions') . "
+ SET image = ? WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $this->image, $this->id ]);
+ }
+ }
+
+ /**
+ * Delete image
+ */
+ public function removeImage() {
+ if ($this->hasImage()) {
+ $query = "UPDATE " . self::db()->table('positions') . "
+ SET image = NULL WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $this->id ]);
+ // ignore unlink errors
+ uUpload::delete($this->image);
+ $this->image = null;
+ }
+ }
+
+ /**
+ * 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);
+ $lat2 = deg2rad($target->latitude);
+ $lon2 = deg2rad($target->longitude);
+ $latD = $lat2 - $lat1;
+ $lonD = $lon2 - $lon1;
+ $bearing = 2 * asin(sqrt((sin($latD / 2) ** 2) + cos($lat1) * cos($lat2) * (sin($lonD / 2) ** 2)));
+ return $bearing * 6371000;
+ }
+
+ /**
+ * Calculate time elapsed since target point
+ *
+ * @param uPosition $target Target position
+ * @return int Number of seconds
+ */
+ public function secondsTo($target) {
+ return $this->timestamp - $target->timestamp;
+ }
+
+ /**
+ * Convert database row to uPosition
+ *
+ * @param array $row Row
+ * @return uPosition Position
+ */
+ private static function rowToObject($row) {
+ $position = new uPosition();
+ $position->id = (int) $row['id'];
+ $position->timestamp = (int) $row['tstamp'];
+ $position->userId = (int) $row['user_id'];
+ $position->userLogin = $row['login'];
+ $position->trackId = (int) $row['track_id'];
+ $position->trackName = $row['name'];
+ $position->latitude = (double) $row['latitude'];
+ $position->longitude = (double) $row['longitude'];
+ $position->altitude = (double) $row['altitude'];
+ $position->speed = (double) $row['speed'];
+ $position->bearing = (double) $row['bearing'];
+ $position->accuracy = (int) $row['accuracy'];
+ $position->provider = $row['provider'];
+ $position->comment = $row['comment'];
+ $position->image = $row['image'];
+ $position->isValid = true;
+ return $position;
+ }
+
+ /**
+ * Fill class properties with database query result
+ *
+ * @param string $query Query
+ * @param array|null $params Optional array of bind parameters
+ * @throws PDOException
+ */
+ private function loadWithQuery($query, $params = null) {
+ $stmt = self::db()->prepare($query);
+ $stmt->execute($params);
+
+ $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
+ $stmt->bindColumn('tstamp', $this->timestamp, PDO::PARAM_INT);
+ $stmt->bindColumn('user_id', $this->userId, PDO::PARAM_INT);
+ $stmt->bindColumn('track_id', $this->trackId, PDO::PARAM_INT);
+ $stmt->bindColumn('latitude', $this->latitude);
+ $stmt->bindColumn('longitude', $this->longitude);
+ $stmt->bindColumn('altitude', $this->altitude);
+ $stmt->bindColumn('speed', $this->speed);
+ $stmt->bindColumn('bearing', $this->bearing);
+ $stmt->bindColumn('accuracy', $this->accuracy, PDO::PARAM_INT);
+ $stmt->bindColumn('provider', $this->provider);
+ $stmt->bindColumn('comment', $this->comment);
+ $stmt->bindColumn('image', $this->image);
+ $stmt->bindColumn('login', $this->userLogin);
+ $stmt->bindColumn('name', $this->trackName);
+ if ($stmt->fetch(PDO::FETCH_BOUND)) {
+ $this->isValid = true;
+ }
+ }
+}
+
?>
diff --git a/helpers/track.php b/helpers/track.php
index 6010d41..6fd8a07 100644
--- a/helpers/track.php
+++ b/helpers/track.php
@@ -20,227 +20,227 @@
require_once(ROOT_DIR . "/helpers/db.php");
require_once(ROOT_DIR . "/helpers/position.php");
- /**
- * Track handling
- */
- class uTrack {
- public $id;
- public $userId;
- public $name;
- public $comment;
+/**
+ * Track handling
+ */
+class uTrack {
+ public $id;
+ public $userId;
+ public $name;
+ public $comment;
- public $isValid = false;
+ public $isValid = false;
- /**
- * Constructor
- *
- * @param int $trackId Track id
- */
- public function __construct($trackId = NULL) {
+ /**
+ * Constructor
+ *
+ * @param int $trackId Track id
+ */
+ public function __construct($trackId = null) {
- if (!empty($trackId)) {
- try {
- $query = "SELECT id, user_id, name, comment FROM " . self::db()->table('tracks') . " WHERE id = ? LIMIT 1";
- $stmt = self::db()->prepare($query);
- $stmt->execute([$trackId]);
- $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
- $stmt->bindColumn('user_id', $this->userId, PDO::PARAM_INT);
- $stmt->bindColumn('name', $this->name);
- $stmt->bindColumn('comment', $this->comment);
- if ($stmt->fetch(PDO::FETCH_BOUND)) {
- $this->isValid = true;
- }
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
-
- }
- }
-
- /**
- * Get db instance
- *
- * @return uDb instance
- */
- private static function db() {
- return uDb::getInstance();
- }
-
- /**
- * 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 static function add($userId, $name, $comment = NULL) {
- $trackId = false;
- if (!empty($userId) && !empty($name)) {
- try {
- $table = self::db()->table('tracks');
- $query = "INSERT INTO $table (user_id, name, comment) VALUES (?, ?, ?)";
- $stmt = self::db()->prepare($query);
- $params = [ $userId, $name, $comment ];
- $stmt->execute($params);
- $trackId = (int) self::db()->lastInsertId("${table}_id_seq");
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $trackId;
- }
-
- /**
- * Add new position to track
- *
- * @param int $userId
- * @param int $timestamp Unix time stamp
- * @param double $lat
- * @param double $lon
- * @param double $altitude Optional
- * @param double $speed Optional
- * @param double $bearing Optional
- * @param int $accuracy Optional
- * @param string $provider Optional
- * @param string $comment Optional
- * @param int $imageId Optional
- * @return int|bool New position id in database, false on error
- */
- public function addPosition($userId, $timestamp, $lat, $lon,
- $altitude = NULL, $speed = NULL, $bearing = NULL, $accuracy = NULL,
- $provider = NULL, $comment = NULL, $imageId = NULL) {
- return uPosition::add($userId, $this->id, $timestamp, $lat, $lon,
- $altitude, $speed, $bearing, $accuracy, $provider, $comment, $imageId);
- }
-
- /**
- * Delete track with all positions
- *
- * @return bool True if success, false otherwise
- */
- public function delete() {
- $ret = false;
- if ($this->isValid) {
- // delete positions
- if (uPosition::deleteAll($this->userId, $this->id) === false) {
- return false;
- }
- // delete track metadata
- try {
- $query = "DELETE FROM " . self::db()->table('tracks') . " WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $this->id ]);
- $ret = true;
- $this->id = NULL;
- $this->userId = NULL;
- $this->name = NULL;
- $this->comment = NULL;
- $this->isValid = false;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Update track
- *
- * @param string|null $name New name (not empty string) or NULL if not changed
- * @param string|null $comment New comment or NULL if not changed (to remove content use empty string: "")
- * @return bool True if success, false otherwise
- */
- public function update($name = NULL, $comment = NULL) {
- $ret = false;
- if (empty($name)) { $name = $this->name; }
- if (is_null($comment)) { $comment = $this->comment; }
- if ($comment === "") { $comment = NULL; }
- if ($this->isValid) {
- try {
- $query = "UPDATE " . self::db()->table('tracks') . " SET name = ?, comment = ? WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $params = [ $name, $comment, $this->id ];
- $stmt->execute($params);
- $ret = true;
- $this->name = $name;
- $this->comment = $comment;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Delete all user's tracks
- *
- * @param string $userId User id
- * @return bool True if success, false otherwise
- */
- public static function deleteAll($userId) {
- $ret = false;
- if (!empty($userId) && uPosition::deleteAll($userId) === true) {
- // remove all tracks
- try {
- $query = "DELETE FROM " . self::db()->table('tracks') . " WHERE user_id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $userId ]);
- $ret = true;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Get all tracks
- *
- * @param int $userId Optional limit to user id
- * @return array|bool Array of uTrack tracks, false on error
- */
- public static function getAll($userId = NULL) {
- if (!empty($userId)) {
- $where = "WHERE user_id=" . self::db()->quote($userId);
- } else {
- $where = "";
- }
- $query = "SELECT id, user_id, name, comment FROM " . self::db()->table('tracks') . " $where ORDER BY id DESC";
+ if (!empty($trackId)) {
try {
- $result = self::db()->query($query);
- $trackArr = [];
- while ($row = $result->fetch()) {
- $trackArr[] = self::rowToObject($row);
+ $query = "SELECT id, user_id, name, comment FROM " . self::db()->table('tracks') . " WHERE id = ? LIMIT 1";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([$trackId]);
+ $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
+ $stmt->bindColumn('user_id', $this->userId, PDO::PARAM_INT);
+ $stmt->bindColumn('name', $this->name);
+ $stmt->bindColumn('comment', $this->comment);
+ if ($stmt->fetch(PDO::FETCH_BOUND)) {
+ $this->isValid = true;
}
} catch (PDOException $e) {
// TODO: handle exception
syslog(LOG_ERR, $e->getMessage());
- $trackArr = false;
}
- return $trackArr;
- }
- /**
- * Convert database row to uTrack
- *
- * @param array $row Row
- * @return uTrack Track
- */
- private static function rowToObject($row) {
- $track = new uTrack();
- $track->id = (int) $row['id'];
- $track->userId = (int) $row['user_id'];
- $track->name = $row['name'];
- $track->comment = $row['comment'];
- $track->isValid = true;
- return $track;
}
}
+ /**
+ * Get db instance
+ *
+ * @return uDb instance
+ */
+ private static function db() {
+ return uDb::getInstance();
+ }
+
+ /**
+ * 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 static function add($userId, $name, $comment = null) {
+ $trackId = false;
+ if (!empty($userId) && !empty($name)) {
+ try {
+ $table = self::db()->table('tracks');
+ $query = "INSERT INTO $table (user_id, name, comment) VALUES (?, ?, ?)";
+ $stmt = self::db()->prepare($query);
+ $params = [ $userId, $name, $comment ];
+ $stmt->execute($params);
+ $trackId = (int) self::db()->lastInsertId("${table}_id_seq");
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $trackId;
+ }
+
+ /**
+ * Add new position to track
+ *
+ * @param int $userId
+ * @param int $timestamp Unix time stamp
+ * @param double $lat
+ * @param double $lon
+ * @param double $altitude Optional
+ * @param double $speed Optional
+ * @param double $bearing Optional
+ * @param int $accuracy Optional
+ * @param string $provider Optional
+ * @param string $comment Optional
+ * @param int $imageId Optional
+ * @return int|bool New position id in database, false on error
+ */
+ public function addPosition($userId, $timestamp, $lat, $lon,
+ $altitude = null, $speed = null, $bearing = null, $accuracy = null,
+ $provider = null, $comment = null, $imageId = null) {
+ return uPosition::add($userId, $this->id, $timestamp, $lat, $lon,
+ $altitude, $speed, $bearing, $accuracy, $provider, $comment, $imageId);
+ }
+
+ /**
+ * Delete track with all positions
+ *
+ * @return bool True if success, false otherwise
+ */
+ public function delete() {
+ $ret = false;
+ if ($this->isValid) {
+ // delete positions
+ if (uPosition::deleteAll($this->userId, $this->id) === false) {
+ return false;
+ }
+ // delete track metadata
+ try {
+ $query = "DELETE FROM " . self::db()->table('tracks') . " WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $this->id ]);
+ $ret = true;
+ $this->id = null;
+ $this->userId = null;
+ $this->name = null;
+ $this->comment = null;
+ $this->isValid = false;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Update track
+ *
+ * @param string|null $name New name (not empty string) or null if not changed
+ * @param string|null $comment New comment or null if not changed (to remove content use empty string: "")
+ * @return bool True if success, false otherwise
+ */
+ public function update($name = null, $comment = null) {
+ $ret = false;
+ if (empty($name)) { $name = $this->name; }
+ if (is_null($comment)) { $comment = $this->comment; }
+ if ($comment === "") { $comment = null; }
+ if ($this->isValid) {
+ try {
+ $query = "UPDATE " . self::db()->table('tracks') . " SET name = ?, comment = ? WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $params = [ $name, $comment, $this->id ];
+ $stmt->execute($params);
+ $ret = true;
+ $this->name = $name;
+ $this->comment = $comment;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Delete all user's tracks
+ *
+ * @param string $userId User id
+ * @return bool True if success, false otherwise
+ */
+ public static function deleteAll($userId) {
+ $ret = false;
+ if (!empty($userId) && uPosition::deleteAll($userId) === true) {
+ // remove all tracks
+ try {
+ $query = "DELETE FROM " . self::db()->table('tracks') . " WHERE user_id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $userId ]);
+ $ret = true;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Get all tracks
+ *
+ * @param int $userId Optional limit to user id
+ * @return array|bool Array of uTrack tracks, false on error
+ */
+ public static function getAll($userId = null) {
+ if (!empty($userId)) {
+ $where = "WHERE user_id=" . self::db()->quote($userId);
+ } else {
+ $where = "";
+ }
+ $query = "SELECT id, user_id, name, comment FROM " . self::db()->table('tracks') . " $where ORDER BY id DESC";
+ try {
+ $result = self::db()->query($query);
+ $trackArr = [];
+ while ($row = $result->fetch()) {
+ $trackArr[] = self::rowToObject($row);
+ }
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ $trackArr = false;
+ }
+ return $trackArr;
+ }
+
+ /**
+ * Convert database row to uTrack
+ *
+ * @param array $row Row
+ * @return uTrack Track
+ */
+ private static function rowToObject($row) {
+ $track = new uTrack();
+ $track->id = (int) $row['id'];
+ $track->userId = (int) $row['user_id'];
+ $track->name = $row['name'];
+ $track->comment = $row['comment'];
+ $track->isValid = true;
+ return $track;
+ }
+}
+
?>
\ No newline at end of file
diff --git a/helpers/upload.php b/helpers/upload.php
index ddbec56..d01546d 100644
--- a/helpers/upload.php
+++ b/helpers/upload.php
@@ -61,20 +61,20 @@ class uUpload {
/**
* Get file extension for given mime
* @param $mime
- * @return string|null Extension or NULL if not found
+ * @return string|null Extension or null if not found
*/
private static function getExtension($mime) {
if (self::isKnownMime($mime)) {
return self::getMimeMap()[$mime];
}
- return NULL;
+ return null;
}
/**
* Save file to uploads, basic sanitizing
* @param array $uploaded File meta array from $_FILES[]
* @param int $trackId
- * @return string|NULL Unique file name, null on error
+ * @return string|null Unique file name, null on error
*/
public static function add($uploaded, $trackId) {
try {
@@ -82,7 +82,7 @@ class uUpload {
} catch (Exception $e) {
syslog(LOG_ERR, $e->getMessage());
// save exception to txt file as image replacement?
- return NULL;
+ return null;
}
$extension = self::getExtension($fileMeta[self::META_TYPE]);
@@ -93,7 +93,7 @@ class uUpload {
if (move_uploaded_file($fileMeta[self::META_TMP_NAME], self::$uploadDir . $fileName)) {
return $fileName;
}
- return NULL;
+ return null;
}
/**
@@ -140,7 +140,7 @@ class uUpload {
$uploadErrors[UPLOAD_ERR_CANT_WRITE] = "Failed to write file to disk";
$uploadErrors[UPLOAD_ERR_EXTENSION] = "A PHP extension stopped file upload";
- $file = NULL;
+ $file = null;
$fileError = isset($fileMeta[self::META_ERROR]) ? $fileMeta[self::META_ERROR] : UPLOAD_ERR_OK;
if ($fileMeta[self::META_SIZE] > uUtils::getSystemUploadLimit() && $fileError == UPLOAD_ERR_OK) {
$fileError = UPLOAD_ERR_FORM_SIZE;
diff --git a/helpers/user.php b/helpers/user.php
index b878343..67c5d87 100644
--- a/helpers/user.php
+++ b/helpers/user.php
@@ -20,222 +20,222 @@
require_once(ROOT_DIR . "/helpers/track.php");
require_once(ROOT_DIR . "/helpers/position.php");
- /**
- * User handling routines
- */
- class uUser {
- public $id;
- public $login;
- public $hash;
- public $isAdmin = false;
- public $isValid = false;
+/**
+ * User handling routines
+ */
+class uUser {
+ public $id;
+ public $login;
+ public $hash;
+ public $isAdmin = false;
+ public $isValid = false;
- /**
- * Constructor
- *
- * @param string $login Login
- */
- public function __construct($login = NULL) {
- if (!empty($login)) {
- try {
- $query = "SELECT id, login, password, admin FROM " . self::db()->table('users') . " WHERE login = ? LIMIT 1";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $login ]);
- $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
- $stmt->bindColumn('login', $this->login);
- $stmt->bindColumn('password', $this->hash);
- $stmt->bindColumn('admin', $this->isAdmin, PDO::PARAM_BOOL);
- if ($stmt->fetch(PDO::FETCH_BOUND)) {
- $this->isValid = true;
- }
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- }
-
- /**
- * Get db instance
- *
- * @return uDb instance
- */
- private static function db() {
- return uDb::getInstance();
- }
-
- /**
- * Add new user
- *
- * @param string $login Login
- * @param string $pass Password
- * @param bool $isAdmin Is admin
- * @return int|bool New user id, false on error
- */
- public static function add($login, $pass, $isAdmin = false) {
- $userid = false;
- if (!empty($login) && !empty($pass)) {
- $hash = password_hash($pass, PASSWORD_DEFAULT);
- $table = self::db()->table('users');
- try {
- $query = "INSERT INTO $table (login, password, admin) VALUES (?, ?, ?)";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $login, $hash, (int) $isAdmin ]);
- $userid = (int) self::db()->lastInsertId("${table}_id_seq");
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $userid;
- }
-
- /**
- * Delete user
- * This will also delete all user's positions and tracks
- *
- * @return bool True if success, false otherwise
- */
- public function delete() {
- $ret = false;
- if ($this->isValid) {
- // remove tracks and positions
- if (uTrack::deleteAll($this->id) === false) {
- return false;
- }
- // remove user
- try {
- $query = "DELETE FROM " . self::db()->table('users') . " WHERE id = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $this->id ]);
- $ret = true;
- $this->id = NULL;
- $this->login = NULL;
- $this->hash = NULL;
- $this->isValid = false;
- $this->isAdmin = false;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- return $ret;
- }
-
- /**
- * Set user admin status
- *
- * @param bool $isAdmin True if is admin
- * @return bool True on success, false otherwise
- */
- public function setAdmin($isAdmin) {
- $ret = false;
+ /**
+ * Constructor
+ *
+ * @param string $login Login
+ */
+ public function __construct($login = null) {
+ if (!empty($login)) {
try {
- $query = "UPDATE " . self::db()->table('users') . " SET admin = ? WHERE login = ?";
+ $query = "SELECT id, login, password, admin FROM " . self::db()->table('users') . " WHERE login = ? LIMIT 1";
$stmt = self::db()->prepare($query);
- $stmt->execute([ (int) $isAdmin, $this->login ]);
- $ret = true;
- $this->isAdmin = $isAdmin;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- return $ret;
- }
-
- /**
- * Set user password
- *
- * @param string $pass Password
- * @return bool True on success, false otherwise
- */
- public function setPass($pass) {
- $ret = false;
- if (!empty($this->login) && !empty($pass)) {
- $hash = password_hash($pass, PASSWORD_DEFAULT);
- try {
- $query = "UPDATE " . self::db()->table('users') . " SET password = ? WHERE login = ?";
- $stmt = self::db()->prepare($query);
- $stmt->execute([ $hash, $this->login ]);
- $ret = true;
- $this->hash = $hash;
- } catch (PDOException $e) {
- // TODO: handle exception
- syslog(LOG_ERR, $e->getMessage());
- }
- }
- 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
- * @return uUser
- */
- public static function getFromSession() {
- $user = new uUser();
- if (isset($_SESSION['user'])) {
- $sessionUser = $_SESSION['user'];
- $user->id = $sessionUser->id;
- $user->login = $sessionUser->login;
- $user->hash = $sessionUser->hash;
- $user->isAdmin = $sessionUser->isAdmin;
- $user->isValid = $sessionUser->isValid;
- }
- return $user;
- }
-
- /**
- * Get all users
- *
- * @return uUser[]|bool Array of uUser users, false on error
- */
- public static function getAll() {
- try {
- $query = "SELECT id, login, password, admin FROM " . self::db()->table('users') . " ORDER BY login";
- $result = self::db()->query($query);
- $userArr = [];
- while ($row = $result->fetch()) {
- $userArr[] = self::rowToObject($row);
+ $stmt->execute([ $login ]);
+ $stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
+ $stmt->bindColumn('login', $this->login);
+ $stmt->bindColumn('password', $this->hash);
+ $stmt->bindColumn('admin', $this->isAdmin, PDO::PARAM_BOOL);
+ if ($stmt->fetch(PDO::FETCH_BOUND)) {
+ $this->isValid = true;
}
} catch (PDOException $e) {
// TODO: handle exception
syslog(LOG_ERR, $e->getMessage());
- $userArr = false;
}
- return $userArr;
- }
-
- /**
- * Convert database row to uUser
- *
- * @param array $row Row
- * @return uUser User
- */
- private static function rowToObject($row) {
- $user = new uUser();
- $user->id = (int) $row['id'];
- $user->login = $row['login'];
- $user->hash = $row['password'];
- $user->isAdmin = (bool) $row['admin'];
- $user->isValid = true;
- return $user;
}
}
+
+ /**
+ * Get db instance
+ *
+ * @return uDb instance
+ */
+ private static function db() {
+ return uDb::getInstance();
+ }
+
+ /**
+ * Add new user
+ *
+ * @param string $login Login
+ * @param string $pass Password
+ * @param bool $isAdmin Is admin
+ * @return int|bool New user id, false on error
+ */
+ public static function add($login, $pass, $isAdmin = false) {
+ $userid = false;
+ if (!empty($login) && !empty($pass)) {
+ $hash = password_hash($pass, PASSWORD_DEFAULT);
+ $table = self::db()->table('users');
+ try {
+ $query = "INSERT INTO $table (login, password, admin) VALUES (?, ?, ?)";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $login, $hash, (int) $isAdmin ]);
+ $userid = (int) self::db()->lastInsertId("${table}_id_seq");
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $userid;
+ }
+
+ /**
+ * Delete user
+ * This will also delete all user's positions and tracks
+ *
+ * @return bool True if success, false otherwise
+ */
+ public function delete() {
+ $ret = false;
+ if ($this->isValid) {
+ // remove tracks and positions
+ if (uTrack::deleteAll($this->id) === false) {
+ return false;
+ }
+ // remove user
+ try {
+ $query = "DELETE FROM " . self::db()->table('users') . " WHERE id = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $this->id ]);
+ $ret = true;
+ $this->id = null;
+ $this->login = null;
+ $this->hash = null;
+ $this->isValid = false;
+ $this->isAdmin = false;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ return $ret;
+ }
+
+ /**
+ * Set user admin status
+ *
+ * @param bool $isAdmin True if is admin
+ * @return bool True on success, false otherwise
+ */
+ public function setAdmin($isAdmin) {
+ $ret = false;
+ try {
+ $query = "UPDATE " . self::db()->table('users') . " SET admin = ? WHERE login = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ (int) $isAdmin, $this->login ]);
+ $ret = true;
+ $this->isAdmin = $isAdmin;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ return $ret;
+ }
+
+ /**
+ * Set user password
+ *
+ * @param string $pass Password
+ * @return bool True on success, false otherwise
+ */
+ public function setPass($pass) {
+ $ret = false;
+ if (!empty($this->login) && !empty($pass)) {
+ $hash = password_hash($pass, PASSWORD_DEFAULT);
+ try {
+ $query = "UPDATE " . self::db()->table('users') . " SET password = ? WHERE login = ?";
+ $stmt = self::db()->prepare($query);
+ $stmt->execute([ $hash, $this->login ]);
+ $ret = true;
+ $this->hash = $hash;
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ }
+ }
+ 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
+ * @return uUser
+ */
+ public static function getFromSession() {
+ $user = new uUser();
+ if (isset($_SESSION['user'])) {
+ $sessionUser = $_SESSION['user'];
+ $user->id = $sessionUser->id;
+ $user->login = $sessionUser->login;
+ $user->hash = $sessionUser->hash;
+ $user->isAdmin = $sessionUser->isAdmin;
+ $user->isValid = $sessionUser->isValid;
+ }
+ return $user;
+ }
+
+ /**
+ * Get all users
+ *
+ * @return uUser[]|bool Array of uUser users, false on error
+ */
+ public static function getAll() {
+ try {
+ $query = "SELECT id, login, password, admin FROM " . self::db()->table('users') . " ORDER BY login";
+ $result = self::db()->query($query);
+ $userArr = [];
+ while ($row = $result->fetch()) {
+ $userArr[] = self::rowToObject($row);
+ }
+ } catch (PDOException $e) {
+ // TODO: handle exception
+ syslog(LOG_ERR, $e->getMessage());
+ $userArr = false;
+ }
+ return $userArr;
+ }
+
+ /**
+ * Convert database row to uUser
+ *
+ * @param array $row Row
+ * @return uUser User
+ */
+ private static function rowToObject($row) {
+ $user = new uUser();
+ $user->id = (int) $row['id'];
+ $user->login = $row['login'];
+ $user->hash = $row['password'];
+ $user->isAdmin = (bool) $row['admin'];
+ $user->isValid = true;
+ return $user;
+ }
+}
?>
diff --git a/helpers/utils.php b/helpers/utils.php
index 402e06f..f82ab6a 100644
--- a/helpers/utils.php
+++ b/helpers/utils.php
@@ -17,211 +17,211 @@
* along with this program; if not, see .
*/
- /**
- * Various util functions
- */
- class uUtils {
-
- /**
- * Calculate maximum allowed size of uploaded file
- * for current PHP settings
- *
- * @return int Number of bytes
- */
- public static function getSystemUploadLimit() {
- $upload_max_filesize = self::iniGetBytes('upload_max_filesize');
- $post_max_size = self::iniGetBytes('post_max_size');
- // post_max_size = 0 means unlimited size
- if ($post_max_size === 0) { $post_max_size = $upload_max_filesize; }
- $memory_limit = self::iniGetBytes('memory_limit');
- // memory_limit = -1 means no limit
- if ($memory_limit < 0) { $memory_limit = $post_max_size; }
- return min($upload_max_filesize, $post_max_size, $memory_limit);
- }
-
- /**
- * @param $path string Path
- * @return bool True if is absolute
- */
- public static function isAbsolutePath($path) {
- return $path[0] === '/' || $path[0] === '\\' || preg_match('/^[a-zA-Z]:\\\\/', $path);
- }
-
- /**
- * Get number of bytes from ini parameter.
- * Optionally parses shorthand byte values (G, M, B)
- *
- * @param string $iniParam Ini parameter name
- * @return int Bytes
- * @noinspection PhpMissingBreakStatementInspection
- */
- private static function iniGetBytes($iniParam) {
- $iniStr = ini_get($iniParam);
- $val = (float) $iniStr;
- $suffix = substr(trim($iniStr), -1);
- if (ctype_alpha($suffix)) {
- switch (strtolower($suffix)) {
- case 'g':
- $val *= 1024;
- case 'm':
- $val *= 1024;
- case 'k':
- $val *= 1024;
- }
- }
- return (int) $val;
- }
-
- /**
- * Exit with error message
- *
- * @param string $errorMessage Message
- * @param array|null $extra Optional array of extra parameters
- */
- public static function exitWithError($errorMessage, $extra = NULL) {
- $extra['message'] = $errorMessage;
- self::exitWithStatus(true, $extra);
- }
-
- /**
- * Exit with successful status code
- *
- * @param array|null $extra Optional array of extra parameters
- */
- public static function exitWithSuccess($extra = NULL) {
- self::exitWithStatus(false, $extra);
- }
-
- /**
- * Exit with xml response
- * @param boolean $isError Error if true
- * @param array|null $extra Optional array of extra parameters
- */
- private static function exitWithStatus($isError, $extra = NULL) {
- $output = [];
- if ($isError) {
- $output["error"] = true;
- }
- if (!empty($extra)) {
- foreach ($extra as $key => $value) {
- $output[$key] = $value;
- }
- }
- header("Content-type: application/json");
- echo json_encode($output);
- exit;
- }
-
- /**
- * Calculate app base URL
- * Returned URL has trailing slash.
- *
- * @return string URL
- */
- public static function getBaseUrl() {
- $proto = (!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] === "" || $_SERVER["HTTPS"] === "off") ? "http://" : "https://";
- // Check if we are behind an https proxy
- if (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] === "https") {
- $proto = "https://";
- }
- $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : "";
- if (realpath($_SERVER["SCRIPT_FILENAME"])) {
- $scriptPath = substr(dirname(realpath($_SERVER["SCRIPT_FILENAME"])), strlen(ROOT_DIR));
- } else {
- // for phpunit
- $scriptPath = substr(dirname($_SERVER["SCRIPT_FILENAME"]), strlen(ROOT_DIR));
- }
- $self = dirname($_SERVER["PHP_SELF"]);
- $path = str_replace("\\", "/", substr($self, 0, strlen($self) - strlen($scriptPath)));
-
- return $proto . str_replace("//", "/", $host . $path . "/");
- }
-
- public static function postFloat($name, $default = NULL) {
- return self::requestValue($name, $default, INPUT_POST, FILTER_VALIDATE_FLOAT);
- }
-
- public static function getFloat($name, $default = NULL) {
- return self::requestValue($name, $default, INPUT_GET, FILTER_VALIDATE_FLOAT);
- }
-
- public static function postPass($name, $default = NULL) {
- return self::requestValue($name, $default, INPUT_POST);
- }
-
- public static function postString($name, $default = NULL) {
- return self::requestString($name, $default, INPUT_POST);
- }
-
- public static function getString($name, $default = NULL) {
- return self::requestString($name, $default, INPUT_GET);
- }
-
- public static function postBool($name, $default = NULL) {
- $input = filter_input(INPUT_POST, $name, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- return $input !== null ? (bool) $input : $default;
- }
-
- public static function getBool($name, $default = NULL) {
- $input = filter_input(INPUT_GET, $name, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- return $input !== null ? (bool) $input : $default;
- }
-
- public static function postInt($name, $default = NULL) {
- return self::requestInt($name, $default, INPUT_POST);
- }
-
- public static function getInt($name, $default = NULL) {
- return self::requestInt($name, $default, INPUT_GET);
- }
-
- public static function requestFile($name, $default = NULL) {
- if (isset($_FILES[$name])) {
- $files = $_FILES[$name];
- if (isset($files["name"], $files["type"], $files["size"], $files["tmp_name"])) {
- return $_FILES[$name];
- }
- }
- return $default;
- }
-
- public static function postArray($name, $default = NULL) {
- return ((isset($_POST[$name]) && is_array($_POST[$name])) ? $_POST[$name] : $default);
- }
-
- /**
- * @param string $name Input name
- * @param boolean $checkMime Optionally check mime with known types
- * @return array File metadata array
- * @throws Exception Upload exception
- * @throws ErrorException Internal server exception
- */
- public static function requireFile($name, $checkMime = false) {
- return uUpload::sanitizeUpload($_FILES[$name], $checkMime);
- }
-
- private static function requestString($name, $default, $type) {
- if (is_string(($val = self::requestValue($name, $default, $type)))) {
- return trim($val);
- }
- return $val;
- }
-
- private static function requestInt($name, $default, $type) {
- if (is_float(($val = self::requestValue($name, $default, $type, FILTER_VALIDATE_FLOAT)))) {
- return (int) round($val);
- }
- return self::requestValue($name, $default, $type, FILTER_VALIDATE_INT);
- }
-
- private static function requestValue($name, $default, $type, $filters = FILTER_DEFAULT, $flags = []) {
- $input = filter_input($type, $name, $filters, $flags);
- if ($input !== false && $input !== null) {
- return $input;
- }
- return $default;
- }
+/**
+ * Various util functions
+ */
+class uUtils {
+ /**
+ * Calculate maximum allowed size of uploaded file
+ * for current PHP settings
+ *
+ * @return int Number of bytes
+ */
+ public static function getSystemUploadLimit() {
+ $upload_max_filesize = self::iniGetBytes('upload_max_filesize');
+ $post_max_size = self::iniGetBytes('post_max_size');
+ // post_max_size = 0 means unlimited size
+ if ($post_max_size === 0) { $post_max_size = $upload_max_filesize; }
+ $memory_limit = self::iniGetBytes('memory_limit');
+ // memory_limit = -1 means no limit
+ if ($memory_limit < 0) { $memory_limit = $post_max_size; }
+ return min($upload_max_filesize, $post_max_size, $memory_limit);
}
+ /**
+ * @param $path string Path
+ * @return bool True if is absolute
+ */
+ public static function isAbsolutePath($path) {
+ return $path[0] === '/' || $path[0] === '\\' || preg_match('/^[a-zA-Z]:\\\\/', $path);
+ }
+
+ /**
+ * Get number of bytes from ini parameter.
+ * Optionally parses shorthand byte values (G, M, B)
+ *
+ * @param string $iniParam Ini parameter name
+ * @return int Bytes
+ * @noinspection PhpMissingBreakStatementInspection
+ */
+ private static function iniGetBytes($iniParam) {
+ $iniStr = ini_get($iniParam);
+ $val = (float) $iniStr;
+ $suffix = substr(trim($iniStr), -1);
+ if (ctype_alpha($suffix)) {
+ switch (strtolower($suffix)) {
+ case 'g':
+ $val *= 1024;
+ case 'm':
+ $val *= 1024;
+ case 'k':
+ $val *= 1024;
+ }
+ }
+ return (int) $val;
+ }
+
+ /**
+ * Exit with error message
+ *
+ * @param string $errorMessage Message
+ * @param array|null $extra Optional array of extra parameters
+ */
+ public static function exitWithError($errorMessage, $extra = null) {
+ $extra['message'] = $errorMessage;
+ self::exitWithStatus(true, $extra);
+ }
+
+ /**
+ * Exit with successful status code
+ *
+ * @param array|null $extra Optional array of extra parameters
+ */
+ public static function exitWithSuccess($extra = null) {
+ self::exitWithStatus(false, $extra);
+ }
+
+ /**
+ * Exit with xml response
+ * @param boolean $isError Error if true
+ * @param array|null $extra Optional array of extra parameters
+ */
+ private static function exitWithStatus($isError, $extra = null) {
+ $output = [];
+ if ($isError) {
+ $output["error"] = true;
+ }
+ if (!empty($extra)) {
+ foreach ($extra as $key => $value) {
+ $output[$key] = $value;
+ }
+ }
+ header("Content-type: application/json");
+ echo json_encode($output);
+ exit;
+ }
+
+ /**
+ * Calculate app base URL
+ * Returned URL has trailing slash.
+ *
+ * @return string URL
+ */
+ public static function getBaseUrl() {
+ $proto = (!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] === "" || $_SERVER["HTTPS"] === "off") ? "http://" : "https://";
+ // Check if we are behind an https proxy
+ if (isset($_SERVER["HTTP_X_FORWARDED_PROTO"]) && $_SERVER["HTTP_X_FORWARDED_PROTO"] === "https") {
+ $proto = "https://";
+ }
+ $host = isset($_SERVER["HTTP_HOST"]) ? $_SERVER["HTTP_HOST"] : "";
+ if (realpath($_SERVER["SCRIPT_FILENAME"])) {
+ $scriptPath = substr(dirname(realpath($_SERVER["SCRIPT_FILENAME"])), strlen(ROOT_DIR));
+ } else {
+ // for phpunit
+ $scriptPath = substr(dirname($_SERVER["SCRIPT_FILENAME"]), strlen(ROOT_DIR));
+ }
+ $self = dirname($_SERVER["PHP_SELF"]);
+ $path = str_replace("\\", "/", substr($self, 0, strlen($self) - strlen($scriptPath)));
+
+ return $proto . str_replace("//", "/", $host . $path . "/");
+ }
+
+ public static function postFloat($name, $default = null) {
+ return self::requestValue($name, $default, INPUT_POST, FILTER_VALIDATE_FLOAT);
+ }
+
+ public static function getFloat($name, $default = null) {
+ return self::requestValue($name, $default, INPUT_GET, FILTER_VALIDATE_FLOAT);
+ }
+
+ public static function postPass($name, $default = null) {
+ return self::requestValue($name, $default, INPUT_POST);
+ }
+
+ public static function postString($name, $default = null) {
+ return self::requestString($name, $default, INPUT_POST);
+ }
+
+ public static function getString($name, $default = null) {
+ return self::requestString($name, $default, INPUT_GET);
+ }
+
+ public static function postBool($name, $default = null) {
+ $input = filter_input(INPUT_POST, $name, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
+ return $input !== null ? (bool) $input : $default;
+ }
+
+ public static function getBool($name, $default = null) {
+ $input = filter_input(INPUT_GET, $name, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
+ return $input !== null ? (bool) $input : $default;
+ }
+
+ public static function postInt($name, $default = null) {
+ return self::requestInt($name, $default, INPUT_POST);
+ }
+
+ public static function getInt($name, $default = null) {
+ return self::requestInt($name, $default, INPUT_GET);
+ }
+
+ public static function requestFile($name, $default = null) {
+ if (isset($_FILES[$name])) {
+ $files = $_FILES[$name];
+ if (isset($files["name"], $files["type"], $files["size"], $files["tmp_name"])) {
+ return $_FILES[$name];
+ }
+ }
+ return $default;
+ }
+
+ public static function postArray($name, $default = null) {
+ return ((isset($_POST[$name]) && is_array($_POST[$name])) ? $_POST[$name] : $default);
+ }
+
+ /**
+ * @param string $name Input name
+ * @param boolean $checkMime Optionally check mime with known types
+ * @return array File metadata array
+ * @throws Exception Upload exception
+ * @throws ErrorException Internal server exception
+ */
+ public static function requireFile($name, $checkMime = false) {
+ return uUpload::sanitizeUpload($_FILES[$name], $checkMime);
+ }
+
+ private static function requestString($name, $default, $type) {
+ if (is_string(($val = self::requestValue($name, $default, $type)))) {
+ return trim($val);
+ }
+ return $val;
+ }
+
+ private static function requestInt($name, $default, $type) {
+ if (is_float(($val = self::requestValue($name, $default, $type, FILTER_VALIDATE_FLOAT)))) {
+ return (int) round($val);
+ }
+ return self::requestValue($name, $default, $type, FILTER_VALIDATE_INT);
+ }
+
+ private static function requestValue($name, $default, $type, $filters = FILTER_DEFAULT, $flags = []) {
+ $input = filter_input($type, $name, $filters, $flags);
+ if ($input !== false && $input !== null) {
+ return $input;
+ }
+ return $default;
+ }
+
+}
+
?>
diff --git a/index.php b/index.php
index 4201515..bc72595 100644
--- a/index.php
+++ b/index.php
@@ -17,32 +17,32 @@
* along with this program; if not, see .
*/
- require_once(__DIR__ . '/helpers/auth.php');
- require_once(ROOT_DIR . '/helpers/config.php');
- require_once(ROOT_DIR . '/helpers/position.php');
- require_once(ROOT_DIR . '/helpers/track.php');
- require_once(ROOT_DIR . '/helpers/utils.php');
- require_once(ROOT_DIR . '/helpers/lang.php');
+require_once(__DIR__ . '/helpers/auth.php');
+require_once(ROOT_DIR . '/helpers/config.php');
+require_once(ROOT_DIR . '/helpers/position.php');
+require_once(ROOT_DIR . '/helpers/track.php');
+require_once(ROOT_DIR . '/helpers/utils.php');
+require_once(ROOT_DIR . '/helpers/lang.php');
- $login = uUtils::postString('user');
- $pass = uUtils::postPass('pass');
- $action = uUtils::postString('action');
+$login = uUtils::postString('user');
+$pass = uUtils::postPass('pass');
+$action = uUtils::postString('action');
- $config = uConfig::getInstance();
- $lang = (new uLang($config))->getStrings();
- $langsArr = uLang::getLanguages();
+$config = uConfig::getInstance();
+$lang = (new uLang($config))->getStrings();
+$langsArr = uLang::getLanguages();
- $auth = new uAuth();
- if ($action === 'auth') {
- $auth->checkLogin($login, $pass);
- }
+$auth = new uAuth();
+if ($action === 'auth') {
+ $auth->checkLogin($login, $pass);
+}
- if ($action === 'auth' && !$auth->isAuthenticated()) {
- $auth->exitWithRedirect('login.php?auth_error=1');
- }
- if ($config->requireAuthentication && !$auth->isAuthenticated()) {
- $auth->exitWithRedirect('login.php');
- }
+if ($action === 'auth' && !$auth->isAuthenticated()) {
+ $auth->exitWithRedirect('login.php?auth_error=1');
+}
+if ($config->requireAuthentication && !$auth->isAuthenticated()) {
+ $auth->exitWithRedirect('login.php');
+}
?>
diff --git a/js/src/configdialogmodel.js b/js/src/configdialogmodel.js
index 21c516d..b66aa4d 100644
--- a/js/src/configdialogmodel.js
+++ b/js/src/configdialogmodel.js
@@ -199,7 +199,7 @@ export default class ConfigDialogModel extends ViewModel {
}
return `
${$._('editingconfig')}
-