Minor formatting changes

This commit is contained in:
Bartek Fabiszewski 2022-03-19 17:48:44 +01:00
parent 7920705d2b
commit 1166cfc4d7
20 changed files with 1854 additions and 1852 deletions

View File

@ -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;

View File

@ -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");
}

View File

@ -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");

View File

@ -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 {

View File

@ -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");
}

View File

@ -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 {

View File

@ -17,185 +17,185 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
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;
}
}

View File

@ -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));
}
}
?>

View File

@ -17,100 +17,100 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
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;
}
}
?>

View File

@ -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;
}
}
}
?>

View File

@ -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;
}
}
?>

View File

@ -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;

View File

@ -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;
}
}
?>

View File

@ -17,211 +17,211 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/**
* 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;
}
}
?>

View File

@ -17,32 +17,32 @@
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
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');
}
?>
<!DOCTYPE html>

View File

@ -199,7 +199,7 @@ export default class ConfigDialogModel extends ViewModel {
}
return `<div><img style="vertical-align: bottom; margin-right: 10px;" src="images/settings.svg" alt="${$._('settings')}"> <b>${$._('editingconfig')}</b></div>
<div style="clear: both; padding-bottom: 1em;"></div>
<form id="configForm">
<form id="config-form">
<label><b>${$._('language')}</b>
<select data-bind="lang">
${langOptions}

View File

@ -138,7 +138,7 @@ foreach ($gpxFiles as $i => $gpxFile) {
$trackCnt = 0;
foreach ($gpx->trk as $trk) {
$trackName = empty($trk->name) ? $gpxName : (string) $trk->name;
$metaName = empty($gpx->metadata->name) ? NULL : (string) $gpx->metadata->name;
$metaName = empty($gpx->metadata->name) ? null : (string) $gpx->metadata->name;
$trackId = uTrack::add($userId, $trackName, $metaName);
if ($trackId === false) {
uUtils::exitWithError($lang["servererror"]);
@ -154,10 +154,10 @@ foreach ($gpxFiles as $i => $gpxFile) {
uUtils::exitWithError($lang["iparsefailure"]);
}
$time = isset($point->time) ? strtotime($point->time) : 0;
$altitude = isset($point->ele) ? (double) $point->ele : NULL;
$speed = NULL;
$bearing = NULL;
$accuracy = NULL;
$altitude = isset($point->ele) ? (double) $point->ele : null;
$speed = null;
$bearing = null;
$accuracy = null;
$provider = "gps";
if (!empty($point->extensions)) {
// parse ulogger extensions
@ -169,7 +169,7 @@ foreach ($gpxFiles as $i => $gpxFile) {
}
$ret = $track->addPosition($userId,
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
$speed, $bearing, $accuracy, $provider, NULL, NULL);
$speed, $bearing, $accuracy, $provider, null, null);
if ($ret === false) {
$track->delete();
uUtils::exitWithError($lang["servererror"]);

View File

@ -100,8 +100,8 @@ if ($trackId && $userId) {
$xml->setIndent(true);
$xml->startDocument("1.0", "utf-8");
$xml->startElement("kml");
$xml->writeAttributeNs("xsi", "schemaLocation", NULL, "http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd");
$xml->writeAttributeNs("xmlns", "xsi", NULL, "http://www.w3.org/2001/XMLSchema-instance");
$xml->writeAttributeNs("xsi", "schemaLocation", null, "http://www.opengis.net/kml/2.2 http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd");
$xml->writeAttributeNs("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
$xml->writeAttribute("xmlns", "http://www.opengis.net/kml/2.2");
$xml->startElement("Document");
$xml->writeElement("name", $positionsArr[0]->trackName);
@ -132,7 +132,7 @@ if ($trackId && $userId) {
if(++$i === count($positionsArr)) { $style = "#greenStyle"; } // last element
$xml->startElement("Placemark");
$xml->writeAttribute("id", "point_{$position->id}");
$description =
$description =
"<div style=\"font-weight: bolder; padding-bottom: 10px; border-bottom: 1px solid gray;\">" .
"{$lang["user"]}: " . htmlspecialchars($position->userLogin) . "<br>{$lang["track"]}: " . htmlspecialchars($position->trackName) .
"</div>" .
@ -151,7 +151,7 @@ if ($trackId && $userId) {
$xml->endElement();
$xml->writeElement("styleUrl", $style);
$xml->startElement("Point");
$coordinate[$i] = "{$position->longitude},{$position->latitude}" . (!is_null($position->altitude) ? ",{$position->altitude}" : "");
$coordinate[$i] = "{$position->longitude},{$position->latitude}" . (!is_null($position->altitude) ? ",{$position->altitude}" : "");
$xml->writeElement("coordinates", $coordinate[$i]);
$xml->endElement();
$xml->endElement();
@ -182,9 +182,9 @@ if ($trackId && $userId) {
$xml->startDocument("1.0", "utf-8");
$xml->startElement("gpx");
$xml->writeAttribute("xmlns", "http://www.topografix.com/GPX/1/1");
$xml->writeAttributeNs("xsi", "schemaLocation", NULL, "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd https://github.com/bfabiszewski/ulogger-android/1 https://raw.githubusercontent.com/bfabiszewski/ulogger-server/master/scripts/gpx_extensions1.xsd");
$xml->writeAttributeNs("xmlns", "xsi", NULL, "http://www.w3.org/2001/XMLSchema-instance");
$xml->writeAttributeNs("xmlns", "ulogger", NULL, "https://github.com/bfabiszewski/ulogger-android/1");
$xml->writeAttributeNs("xsi", "schemaLocation", null, "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd https://github.com/bfabiszewski/ulogger-android/1 https://raw.githubusercontent.com/bfabiszewski/ulogger-server/master/scripts/gpx_extensions1.xsd");
$xml->writeAttributeNs("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
$xml->writeAttributeNs("xmlns", "ulogger", null, "https://github.com/bfabiszewski/ulogger-android/1");
$xml->writeAttribute("creator", "μlogger-server " . $config->version);
$xml->writeAttribute("version", "1.1");
$xml->startElement("metadata");
@ -194,46 +194,47 @@ if ($trackId && $userId) {
$xml->startElement("trk");
$xml->writeElement("name", $positionsArr[0]->trackName);
$xml->startElement("trkseg");
$i = 0;
$totalMeters = 0;
$totalSeconds = 0;
foreach ($positionsArr as $position) {
$distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0;
$seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0;
$prevPosition = $position;
$totalMeters += $distance;
$totalSeconds += $seconds;
$i = 0;
$totalMeters = 0;
$totalSeconds = 0;
foreach ($positionsArr as $position) {
$distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0;
$seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0;
$prevPosition = $position;
$totalMeters += $distance;
$totalSeconds += $seconds;
$xml->startElement("trkpt");
$xml->writeAttribute("lat", $position->latitude);
$xml->writeAttribute("lon", $position->longitude);
if (!is_null($position->altitude)) { $xml->writeElement("ele", $position->altitude); }
if (!is_null($position->altitude)) {
$xml->writeElement("ele", $position->altitude);
}
$xml->writeElement("time", gmdate("Y-m-d\TH:i:s\Z", $position->timestamp));
$xml->writeElement("name", ++$i);
if (!is_null($position->comment)) {
$xml->startElement("desc");
if (!is_null($position->comment)) {
$xml->startElement("desc");
$xml->writeCData($position->comment);
$xml->endElement();
}
if (!is_null($position->speed) || !is_null($position->bearing) || !is_null($position->accuracy) || !is_null($position->provider)) {
$xml->startElement("extensions");
if (!is_null($position->speed)) {
$xml->writeElementNS("ulogger", "speed", NULL, $position->speed);
}
if (!is_null($position->bearing)) {
$xml->writeElementNS("ulogger", "bearing", NULL, $position->bearing);
}
if (!is_null($position->accuracy)) {
$xml->writeElementNS("ulogger", "accuracy", NULL, $position->accuracy);
}
if (!is_null($position->provider)) {
$xml->writeElementNS("ulogger", "provider", NULL, $position->provider);
}
$xml->endElement();
}
$xml->endElement();
$xml->endElement();
}
if (!is_null($position->speed) || !is_null($position->bearing) || !is_null($position->accuracy) || !is_null($position->provider)) {
$xml->startElement("extensions");
if (!is_null($position->speed)) {
$xml->writeElementNS("ulogger", "speed", null, $position->speed);
}
if (!is_null($position->bearing)) {
$xml->writeElementNS("ulogger", "bearing", null, $position->bearing);
}
if (!is_null($position->accuracy)) {
$xml->writeElementNS("ulogger", "accuracy", null, $position->accuracy);
}
if (!is_null($position->provider)) {
$xml->writeElementNS("ulogger", "provider", null, $position->provider);
}
$xml->endElement();
}
$xml->endElement();
}
$xml->endElement();
$xml->endElement();
$xml->endElement();

View File

@ -41,7 +41,7 @@ if ($admin && !$auth->isAdmin()) {
}
$aUser = new uUser($login);
$data = NULL;
$data = null;
switch ($action) {
case 'add':

View File

@ -73,7 +73,7 @@ else if (empty($gpx->trk)) {
$trackList = [];
foreach ($gpx->trk as $trk) {
$trackName = empty($trk->name) ? $gpxName : (string) $trk->name;
$metaName = empty($gpx->metadata->name) ? NULL : (string) $gpx->metadata->name;
$metaName = empty($gpx->metadata->name) ? null : (string) $gpx->metadata->name;
$trackId = uTrack::add($auth->user->id, $trackName, $metaName);
if ($trackId === false) {
uUtils::exitWithError($lang["servererror"]);
@ -89,11 +89,11 @@ foreach ($gpx->trk as $trk) {
uUtils::exitWithError($lang["iparsefailure"]);
}
$time = isset($point->time) ? strtotime($point->time) : 1;
$altitude = isset($point->ele) ? (double) $point->ele : NULL;
$comment = isset($point->desc) && !empty($point->desc) ? (string) $point->desc : NULL;
$speed = NULL;
$bearing = NULL;
$accuracy = NULL;
$altitude = isset($point->ele) ? (double) $point->ele : null;
$comment = isset($point->desc) && !empty($point->desc) ? (string) $point->desc : null;
$speed = null;
$bearing = null;
$accuracy = null;
$provider = "gps";
if (!empty($point->extensions)) {
// parse ulogger extensions
@ -105,7 +105,7 @@ foreach ($gpx->trk as $trk) {
}
$ret = $track->addPosition($auth->user->id,
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
$speed, $bearing, $accuracy, $provider, $comment, NULL);
$speed, $bearing, $accuracy, $provider, $comment, null);
if ($ret === false) {
$track->delete();
uUtils::exitWithError($lang["servererror"]);