Minor formatting changes
This commit is contained in:
parent
7920705d2b
commit
1166cfc4d7
@ -140,10 +140,10 @@ abstract class BaseDatabaseTestCase extends PHPUnit\DbUnit\TestCase {
|
|||||||
*
|
*
|
||||||
* @param string $table Table name
|
* @param string $table Table name
|
||||||
* @param array $rowsArr Array of rows
|
* @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 {
|
private function pdoInsert(string $table, array $rowsArr = []): ?int {
|
||||||
$ret = NULL;
|
$ret = null;
|
||||||
if (!empty($rowsArr)) {
|
if (!empty($rowsArr)) {
|
||||||
$values = ':' . implode(', :', array_keys($rowsArr));
|
$values = ':' . implode(', :', array_keys($rowsArr));
|
||||||
$columns = 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
|
* Execute raw insert query on database
|
||||||
*
|
*
|
||||||
* @param string $query Insert query
|
* @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 {
|
private function pdoInsertRaw(string $query): ?int {
|
||||||
$ret = null;
|
$ret = null;
|
||||||
|
@ -37,19 +37,19 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals(1, (int) $position->id, "Wrong position id");
|
self::assertEquals(1, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
|
||||||
|
|
||||||
$position = $json[1];
|
$position = $json[1];
|
||||||
self::assertEquals(2, (int) $position->id,"Wrong position id");
|
self::assertEquals(2, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
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");
|
self::assertCount(2, $json, "Wrong count of positions");
|
||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals(1, (int) $position->id,"Wrong position id");
|
self::assertEquals(1, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
|
||||||
|
|
||||||
$position = $json[1];
|
$position = $json[1];
|
||||||
self::assertEquals(2, (int) $position->id,"Wrong position id");
|
self::assertEquals(2, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
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");
|
self::assertCount(2, $json, "Wrong count of positions");
|
||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals(1, (int) $position->id,"Wrong position id");
|
self::assertEquals(1, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
|
||||||
|
|
||||||
$position = $json[1];
|
$position = $json[1];
|
||||||
self::assertEquals(2, (int) $position->id,"Wrong position id");
|
self::assertEquals(2, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
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");
|
self::assertCount(1, $json, "Wrong count of positions");
|
||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals(2, (int) $position->id,"Wrong position id");
|
self::assertEquals(2, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
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");
|
self::assertCount(2, $json, "Wrong count of positions");
|
||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals(2, (int) $position->id,"Wrong position id");
|
self::assertEquals(2, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 3, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
|
||||||
|
|
||||||
$position = $json[1];
|
$position = $json[1];
|
||||||
self::assertEquals(3, (int) $position->id,"Wrong position id");
|
self::assertEquals(3, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 2, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 2, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($trackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($trackName, (string) $position->trackname, "Wrong trackname");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,14 +349,14 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
self::assertCount(1, $json, "Wrong count of positions");
|
self::assertCount(1, $json, "Wrong count of positions");
|
||||||
|
|
||||||
$position = $json[0];
|
$position = $json[0];
|
||||||
self::assertEquals($afterId + 1, (int) $position->id,"Wrong position id");
|
self::assertEquals($afterId + 1, (int) $position->id, "Wrong position id");
|
||||||
self::assertEquals($this->testLat + 1, (float) $position->latitude,"Wrong latitude");
|
self::assertEquals($this->testLat + 1, (float) $position->latitude, "Wrong latitude");
|
||||||
self::assertEquals($this->testLon, (float) $position->longitude,"Wrong longitude");
|
self::assertEquals($this->testLon, (float) $position->longitude, "Wrong longitude");
|
||||||
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp,"Wrong timestamp");
|
self::assertEquals($this->testTimestamp + 1, (int) $position->timestamp, "Wrong timestamp");
|
||||||
self::assertEquals($this->testAdminUser, (string) $position->username,"Wrong username");
|
self::assertEquals($this->testAdminUser, (string) $position->username, "Wrong username");
|
||||||
self::assertEquals($this->testTrackName, (string) $position->trackname,"Wrong trackname");
|
self::assertEquals($this->testTrackName, (string) $position->trackname, "Wrong trackname");
|
||||||
self::assertEquals(111195, (int) $position->meters,"Wrong distance delta");
|
self::assertEquals(111195, (int) $position->meters, "Wrong distance delta");
|
||||||
self::assertEquals(1, (int) $position->seconds,"Wrong timestamp 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");
|
self::assertCount(2, $json, "Wrong count of tracks");
|
||||||
|
|
||||||
$track = $json[0];
|
$track = $json[0];
|
||||||
self::assertEquals($this->testTrackId2, (int) $track->id,"Wrong track id");
|
self::assertEquals($this->testTrackId2, (int) $track->id, "Wrong track id");
|
||||||
self::assertEquals($this->testTrackName . "2", (string) $track->name,"Wrong track name");
|
self::assertEquals($this->testTrackName . "2", (string) $track->name, "Wrong track name");
|
||||||
|
|
||||||
$track = $json[1];
|
$track = $json[1];
|
||||||
self::assertEquals($this->testTrackId, (int) $track->id,"Wrong track id");
|
self::assertEquals($this->testTrackId, (int) $track->id, "Wrong track id");
|
||||||
self::assertEquals($this->testTrackName, (string) $track->name,"Wrong track name");
|
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");
|
self::assertCount(2, $json, "Wrong count of tracks");
|
||||||
|
|
||||||
$track = $json[0];
|
$track = $json[0];
|
||||||
self::assertEquals($this->testTrackId2, (int) $track->id,"Wrong track id");
|
self::assertEquals($this->testTrackId2, (int) $track->id, "Wrong track id");
|
||||||
self::assertEquals($this->testTrackName . "2", (string) $track->name,"Wrong track name");
|
self::assertEquals($this->testTrackName . "2", (string) $track->name, "Wrong track name");
|
||||||
|
|
||||||
$track = $json[1];
|
$track = $json[1];
|
||||||
self::assertEquals($this->testTrackId, (int) $track->id,"Wrong track id");
|
self::assertEquals($this->testTrackId, (int) $track->id, "Wrong track id");
|
||||||
self::assertEquals($this->testTrackName, (string) $track->name,"Wrong track name");
|
self::assertEquals($this->testTrackName, (string) $track->name, "Wrong track name");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -626,8 +626,8 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
|
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
self::assertEquals(1, (int) $json->error, "Wrong error status");
|
||||||
self::assertEquals("Wrong old password", (string) $json->message,"Wrong error message");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
self::assertEquals(2, $this->getConnection()->getRowCount("tracks"), "Wrong row count");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -918,7 +918,7 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error, "Wrong error status");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -959,8 +959,8 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
self::assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
self::assertEquals(1, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
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");
|
self::assertEquals(200, $response->getStatusCode(), "Unexpected status code");
|
||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error,"Wrong error status");
|
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");
|
||||||
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,7 +1074,7 @@ class InternalAPITest extends UloggerAPITestCase {
|
|||||||
$json = json_decode($response->getBody());
|
$json = json_decode($response->getBody());
|
||||||
self::assertNotNull($json, "JSON object is null");
|
self::assertNotNull($json, "JSON object is null");
|
||||||
self::assertEquals(1, (int) $json->error, "Wrong error status");
|
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");
|
self::assertEquals(2, $this->getConnection()->getRowCount("users"), "Wrong row count");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +41,11 @@ class PositionTest extends UloggerDatabaseTestCase {
|
|||||||
);
|
);
|
||||||
$this->assertTableContains($expected, $actual, "Wrong actual table data");
|
$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");
|
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");
|
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");
|
self::assertFalse($posId, "Adding position with null longitude should fail");
|
||||||
|
|
||||||
$posId = uPosition::add($userId, $trackId, "", $this->testLat, $this->testLon);
|
$posId = uPosition::add($userId, $trackId, "", $this->testLat, $this->testLon);
|
||||||
@ -156,7 +156,7 @@ class PositionTest extends UloggerDatabaseTestCase {
|
|||||||
self::assertCount(2, $posArr, "Wrong row count");
|
self::assertCount(2, $posArr, "Wrong row count");
|
||||||
$posArr = uPosition::getAll($userId, $trackId);
|
$posArr = uPosition::getAll($userId, $trackId);
|
||||||
self::assertCount(1, $posArr, "Wrong row count");
|
self::assertCount(1, $posArr, "Wrong row count");
|
||||||
$posArr = uPosition::getAll(NULL, $trackId);
|
$posArr = uPosition::getAll(null, $trackId);
|
||||||
self::assertCount(1, $posArr, "Wrong row count");
|
self::assertCount(1, $posArr, "Wrong row count");
|
||||||
$posArr = uPosition::getAll($userId3);
|
$posArr = uPosition::getAll($userId3);
|
||||||
self::assertCount(0, $posArr, "Wrong row count");
|
self::assertCount(0, $posArr, "Wrong row count");
|
||||||
|
@ -72,11 +72,11 @@ class TrackTest extends UloggerDatabaseTestCase {
|
|||||||
);
|
);
|
||||||
$this->assertTableContains($expected, $actual, "Wrong actual table data");
|
$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");
|
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");
|
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");
|
self::assertFalse($posId, "Adding position with null longitude should fail");
|
||||||
|
|
||||||
$posId = $track->addPosition($userId, "", $this->testLat, $this->testLon);
|
$posId = $track->addPosition($userId, "", $this->testLat, $this->testLon);
|
||||||
@ -113,7 +113,7 @@ class TrackTest extends UloggerDatabaseTestCase {
|
|||||||
uTrack::deleteAll($userId);
|
uTrack::deleteAll($userId);
|
||||||
self::assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count");
|
self::assertEquals(1, $this->getConnection()->getRowCount('tracks'), "Wrong row count");
|
||||||
self::assertEquals(1, $this->getConnection()->getRowCount('positions'), "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 {
|
public function testUpdate(): void {
|
||||||
|
@ -75,7 +75,7 @@ class UserTest extends UloggerDatabaseTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function testIsAdmin(): void {
|
public function testIsAdmin(): void {
|
||||||
$this->addTestUser($this->testUser, NULL, true);
|
$this->addTestUser($this->testUser, null, true);
|
||||||
$user = new uUser($this->testUser);
|
$user = new uUser($this->testUser);
|
||||||
self::assertTrue($user->isAdmin, "User should be admin");
|
self::assertTrue($user->isAdmin, "User should be admin");
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ select {
|
|||||||
width: 165px;
|
width: 165px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
color: lightgray;
|
color: lightgray;
|
||||||
background-color: rgba(102, 102, 102, 0.9);
|
background-color: rgba(102, 102, 102, 90%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#menu-button {
|
#menu-button {
|
||||||
@ -122,7 +122,7 @@ select {
|
|||||||
#menu.menu-hidden #menu-button {
|
#menu.menu-hidden #menu-button {
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
border-color: white;
|
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 {
|
#menu.menu-hidden #menu-button a::after {
|
||||||
@ -153,7 +153,7 @@ select {
|
|||||||
margin-top: 0.2em;
|
margin-top: 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
label[for=user] {
|
label[for="user"] {
|
||||||
display: block;
|
display: block;
|
||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
}
|
}
|
||||||
@ -340,7 +340,7 @@ label[for=user] {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: black; /* fallback */
|
background-color: black; /* fallback */
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
background-color: rgba(0, 0, 0, 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal-header {
|
#modal-header {
|
||||||
@ -353,7 +353,7 @@ label[for=user] {
|
|||||||
|
|
||||||
#modal-header button {
|
#modal-header button {
|
||||||
border: none;
|
border: none;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal-body {
|
#modal-body {
|
||||||
@ -363,13 +363,13 @@ label[for=user] {
|
|||||||
transform: translate(-50%, -50%) !important;
|
transform: translate(-50%, -50%) !important;
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
margin: 0 auto 15% auto;
|
margin: 0 auto 15%;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
color: white;
|
color: white;
|
||||||
border: 1px solid #888;
|
border: 1px solid #888;
|
||||||
-webkit-border-radius: 10px;
|
-webkit-border-radius: 10px;
|
||||||
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;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
}
|
}
|
||||||
@ -378,10 +378,10 @@ label[for=user] {
|
|||||||
padding-top: 1em;
|
padding-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal input[type=text],
|
#modal input[type="text"],
|
||||||
#modal input[type=color],
|
#modal input[type="color"],
|
||||||
#modal input[type=number],
|
#modal input[type="number"],
|
||||||
#modal input[type=password] {
|
#modal input[type="password"] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -395,7 +395,7 @@ label[for=user] {
|
|||||||
#modal.image {
|
#modal.image {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
background-color: rgba(45, 45, 45, 0.95);
|
background-color: rgba(45, 45, 45, 95%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#modal.image #modal-body img {
|
#modal.image #modal-body img {
|
||||||
@ -466,11 +466,11 @@ button > * {
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm label {
|
#config-form label {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm label b {
|
#config-form label b {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
@ -479,30 +479,30 @@ button > * {
|
|||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm input[type=text],
|
#config-form input[type="text"],
|
||||||
#configForm input[type=number],
|
#config-form input[type="number"],
|
||||||
#configForm input[type=color],
|
#config-form input[type="color"],
|
||||||
#configForm select {
|
#config-form select {
|
||||||
width: 150px;
|
width: 150px;
|
||||||
margin: 3px 0;
|
margin: 3px 0;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm input[type=checkbox] {
|
#config-form input[type="checkbox"] {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm select {
|
#config-form select {
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm input[type=color] {
|
#config-form input[type="color"] {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#configForm img {
|
#config-form img {
|
||||||
height: 13px;
|
height: 13px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
@ -531,7 +531,7 @@ button > * {
|
|||||||
padding: 6px 20px;
|
padding: 6px 20px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border-top: 1px solid #555;
|
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;
|
z-index: 100000;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: all 1s;
|
transition: all 1s;
|
||||||
@ -596,7 +596,7 @@ button > * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.alert.spinner > span::before, .alert.spinner > span::after {
|
.alert.spinner > span::before, .alert.spinner > span::after {
|
||||||
content: '';
|
content: "";
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -661,8 +661,8 @@ button > * {
|
|||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: #666;
|
background-color: #666;
|
||||||
-webkit-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, 0.2));
|
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 20%));
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-popup::after, .ol-popup::before {
|
.ol-popup::after, .ol-popup::before {
|
||||||
@ -695,7 +695,7 @@ button > * {
|
|||||||
right: -10px;
|
right: -10px;
|
||||||
width: 30px;
|
width: 30px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
background-image: url(../../images/close.svg) !important;
|
background-image: url("../../images/close.svg") !important;
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,11 +710,12 @@ button > * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.gm-style .gm-style-iw-t::after {
|
.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 {
|
.gm-style-iw button {
|
||||||
background-image: url(../../images/close.svg) !important;
|
background-image: url("../../images/close.svg") !important;
|
||||||
background-repeat: no-repeat !important;
|
background-repeat: no-repeat !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,11 +745,11 @@ button > * {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: rgba(0, 60, 136, 0.5);
|
background-color: rgba(0, 60, 136, 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-layerswitcher:hover {
|
.ol-layerswitcher:hover {
|
||||||
background-color: rgba(0, 60, 136, 0.7);
|
background-color: rgba(0, 60, 136, 70%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ol-layerswitcher label {
|
.ol-layerswitcher label {
|
||||||
|
346
helpers/auth.php
346
helpers/auth.php
@ -17,185 +17,185 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!defined('ROOT_DIR')) { define('ROOT_DIR', dirname(__DIR__)); }
|
if (!defined('ROOT_DIR')) { define('ROOT_DIR', dirname(__DIR__)); }
|
||||||
require_once(ROOT_DIR . "/helpers/user.php");
|
require_once(ROOT_DIR . "/helpers/user.php");
|
||||||
require_once(ROOT_DIR . "/helpers/utils.php");
|
require_once(ROOT_DIR . "/helpers/utils.php");
|
||||||
if (!defined('BASE_URL')) { define('BASE_URL', uUtils::getBaseUrl()); }
|
if (!defined('BASE_URL')) { define('BASE_URL', uUtils::getBaseUrl()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Authentication
|
* Authentication
|
||||||
*/
|
*/
|
||||||
class uAuth {
|
class uAuth {
|
||||||
|
|
||||||
/** @var bool Is user authenticated */
|
/** @var bool Is user authenticated */
|
||||||
private $isAuthenticated = false;
|
private $isAuthenticated = false;
|
||||||
/** @var null|uUser */
|
/** @var null|uUser */
|
||||||
public $user;
|
public $user;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$this->sessionStart();
|
$this->sessionStart();
|
||||||
|
|
||||||
$user = uUser::getFromSession();
|
$user = uUser::getFromSession();
|
||||||
if ($user->isValid) {
|
if ($user->isValid) {
|
||||||
$this->setAuthenticated($user);
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
584
helpers/db.php
584
helpers/db.php
@ -19,302 +19,302 @@
|
|||||||
|
|
||||||
require_once(ROOT_DIR . "/helpers/utils.php");
|
require_once(ROOT_DIR . "/helpers/utils.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDO wrapper
|
* PDO wrapper
|
||||||
*/
|
*/
|
||||||
class uDb extends PDO {
|
class uDb extends PDO {
|
||||||
/**
|
/**
|
||||||
* Singleton instance
|
* Singleton instance
|
||||||
*
|
*
|
||||||
* @var uDb Object instance
|
* @var uDb Object instance
|
||||||
*/
|
*/
|
||||||
protected static $instance;
|
protected static $instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table names
|
* Table names
|
||||||
*
|
*
|
||||||
* @var array Array of names
|
* @var array Array of names
|
||||||
*/
|
*/
|
||||||
protected static $tables;
|
protected static $tables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Database driver name
|
* Database driver name
|
||||||
*
|
*
|
||||||
* @var string Driver
|
* @var string Driver
|
||||||
*/
|
*/
|
||||||
protected static $driver;
|
protected static $driver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string Database DSN
|
* @var string Database DSN
|
||||||
*/
|
*/
|
||||||
private static $dbdsn = "";
|
private static $dbdsn = "";
|
||||||
/**
|
/**
|
||||||
* @var string Database user
|
* @var string Database user
|
||||||
*/
|
*/
|
||||||
private static $dbuser = "";
|
private static $dbuser = "";
|
||||||
/**
|
/**
|
||||||
* @var string Database pass
|
* @var string Database pass
|
||||||
*/
|
*/
|
||||||
private static $dbpass = "";
|
private static $dbpass = "";
|
||||||
/**
|
/**
|
||||||
* @var string Optional table names prefix, eg. "ulogger_"
|
* @var string Optional table names prefix, eg. "ulogger_"
|
||||||
*/
|
*/
|
||||||
private static $dbprefix = "";
|
private static $dbprefix = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDO constuctor
|
* PDO constuctor
|
||||||
*
|
*
|
||||||
* @param string $dsn
|
* @param string $dsn
|
||||||
* @param string $user
|
* @param string $user
|
||||||
* @param string $pass
|
* @param string $pass
|
||||||
*/
|
*/
|
||||||
public function __construct($dsn, $user, $pass) {
|
public function __construct($dsn, $user, $pass) {
|
||||||
try {
|
try {
|
||||||
$options = [
|
$options = [
|
||||||
PDO::ATTR_EMULATE_PREPARES => false, // try to use native prepared statements
|
PDO::ATTR_EMULATE_PREPARES => false, // try to use native prepared statements
|
||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // throw exceptions
|
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // throw exceptions
|
||||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // return assoc array by default
|
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // return assoc array by default
|
||||||
];
|
];
|
||||||
@parent::__construct($dsn, $user, $pass, $options);
|
@parent::__construct($dsn, $user, $pass, $options);
|
||||||
self::$driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
|
self::$driver = $this->getAttribute(PDO::ATTR_DRIVER_NAME);
|
||||||
$this->setCharset("utf8");
|
$this->setCharset("utf8");
|
||||||
$this->initTables();
|
$this->initTables();
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
header("HTTP/1.1 503 Service Unavailable");
|
header("HTTP/1.1 503 Service Unavailable");
|
||||||
die("Database connection error (" . $e->getMessage() . ")");
|
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
176
helpers/lang.php
176
helpers/lang.php
@ -17,100 +17,100 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* 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
|
* Available languages
|
||||||
*/
|
*
|
||||||
class uLang {
|
* @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
|
* Application strings
|
||||||
*
|
* Array of key => translation pairs
|
||||||
* @var array
|
*
|
||||||
*/
|
* @var array
|
||||||
private static $languages = [
|
*/
|
||||||
"ca" => "Català",
|
private $strings;
|
||||||
"cs" => "Čeština",
|
/**
|
||||||
"de" => "Deutsch",
|
* Setup script strings
|
||||||
"el" => "Ελληνικά",
|
* Array of key => translation pairs
|
||||||
"en" => "English",
|
*
|
||||||
"es" => "Español",
|
* @var array
|
||||||
"eu" => "Euskera",
|
*/
|
||||||
"fr" => "Français",
|
private $setupStrings;
|
||||||
"it" => "Italiano",
|
|
||||||
"pl" => "Polski",
|
|
||||||
"ru" => "Русский",
|
|
||||||
"sk" => "Slovenčina"
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application strings
|
* Constructor
|
||||||
* Array of key => translation pairs
|
*
|
||||||
*
|
* @param uConfig $config Config
|
||||||
* @var array
|
*/
|
||||||
*/
|
public function __construct($config) {
|
||||||
private $strings;
|
$language = $config->lang;
|
||||||
/**
|
$lang = [];
|
||||||
* Setup script strings
|
$langSetup = [];
|
||||||
* Array of key => translation pairs
|
// always load en base
|
||||||
*
|
require(ROOT_DIR . "/lang/en.php");
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $setupStrings;
|
|
||||||
|
|
||||||
/**
|
// override with translated strings if needed
|
||||||
* Constructor
|
// missing strings will be displayed in English
|
||||||
*
|
if ($language !== "en" && array_key_exists($language, self::$languages)) {
|
||||||
* @param uConfig $config Config
|
require(ROOT_DIR . "/lang/$language.php");
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
@ -21,485 +21,485 @@ require_once(ROOT_DIR . "/helpers/db.php");
|
|||||||
require_once(ROOT_DIR . "/helpers/track.php");
|
require_once(ROOT_DIR . "/helpers/track.php");
|
||||||
require_once(ROOT_DIR . "/helpers/upload.php");
|
require_once(ROOT_DIR . "/helpers/upload.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Positions handling
|
* Positions handling
|
||||||
*/
|
*/
|
||||||
class uPosition {
|
class uPosition {
|
||||||
/** @param int Position id */
|
/** @param int Position id */
|
||||||
public $id;
|
public $id;
|
||||||
/** @param int Unix time stamp */
|
/** @param int Unix time stamp */
|
||||||
public $timestamp;
|
public $timestamp;
|
||||||
/** @param int User id */
|
/** @param int User id */
|
||||||
public $userId;
|
public $userId;
|
||||||
/** @param String User login */
|
/** @param String User login */
|
||||||
public $userLogin;
|
public $userLogin;
|
||||||
/** @param int Track id */
|
/** @param int Track id */
|
||||||
public $trackId;
|
public $trackId;
|
||||||
/** @param String Track name */
|
/** @param String Track name */
|
||||||
public $trackName;
|
public $trackName;
|
||||||
/** @param double Latitude */
|
/** @param double Latitude */
|
||||||
public $latitude;
|
public $latitude;
|
||||||
/** @param double Longitude */
|
/** @param double Longitude */
|
||||||
public $longitude;
|
public $longitude;
|
||||||
/** @param double Altitude */
|
/** @param double Altitude */
|
||||||
public $altitude;
|
public $altitude;
|
||||||
/** @param double Speed */
|
/** @param double Speed */
|
||||||
public $speed;
|
public $speed;
|
||||||
/** @param double Bearing */
|
/** @param double Bearing */
|
||||||
public $bearing;
|
public $bearing;
|
||||||
/** @param int Accuracy */
|
/** @param int Accuracy */
|
||||||
public $accuracy;
|
public $accuracy;
|
||||||
/** @param String Provider */
|
/** @param String Provider */
|
||||||
public $provider;
|
public $provider;
|
||||||
/** @param String Comment */
|
/** @param String Comment */
|
||||||
public $comment;
|
public $comment;
|
||||||
/** @param String Image path */
|
/** @param String Image path */
|
||||||
public $image;
|
public $image;
|
||||||
|
|
||||||
public $isValid = false;
|
public $isValid = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
* @param integer $positionId Position id
|
* @param integer $positionId Position id
|
||||||
*/
|
*/
|
||||||
public function __construct($positionId = NULL) {
|
public function __construct($positionId = null) {
|
||||||
|
|
||||||
if (!empty($positionId)) {
|
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;
|
|
||||||
}
|
|
||||||
$query = "SELECT p.id, " . self::db()->unix_timestamp('p.time') . " AS tstamp, p.user_id, p.track_id,
|
$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.latitude, p.longitude, p.altitude, p.speed, p.bearing, p.accuracy, p.provider,
|
||||||
p.comment, p.image, u.login, t.name
|
p.comment, p.image, u.login, t.name
|
||||||
FROM " . self::db()->table('positions') . " p
|
FROM " . self::db()->table('positions') . " p
|
||||||
LEFT JOIN " . self::db()->table('users') . " u ON (p.user_id = u.id)
|
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)
|
LEFT JOIN " . self::db()->table('tracks') . " t ON (p.track_id = t.id)
|
||||||
$where
|
WHERE p.id = ? LIMIT 1";
|
||||||
ORDER BY p.time DESC, p.id DESC LIMIT 1";
|
$params = [ $positionId ];
|
||||||
$position = new uPosition();
|
|
||||||
try {
|
try {
|
||||||
$position->loadWithQuery($query, $params);
|
$this->loadWithQuery($query, $params);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
// TODO: handle exception
|
// TODO: handle exception
|
||||||
syslog(LOG_ERR, $e->getMessage());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -20,227 +20,227 @@
|
|||||||
require_once(ROOT_DIR . "/helpers/db.php");
|
require_once(ROOT_DIR . "/helpers/db.php");
|
||||||
require_once(ROOT_DIR . "/helpers/position.php");
|
require_once(ROOT_DIR . "/helpers/position.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track handling
|
* Track handling
|
||||||
*/
|
*/
|
||||||
class uTrack {
|
class uTrack {
|
||||||
public $id;
|
public $id;
|
||||||
public $userId;
|
public $userId;
|
||||||
public $name;
|
public $name;
|
||||||
public $comment;
|
public $comment;
|
||||||
|
|
||||||
public $isValid = false;
|
public $isValid = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param int $trackId Track id
|
* @param int $trackId Track id
|
||||||
*/
|
*/
|
||||||
public function __construct($trackId = NULL) {
|
public function __construct($trackId = null) {
|
||||||
|
|
||||||
if (!empty($trackId)) {
|
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";
|
|
||||||
try {
|
try {
|
||||||
$result = self::db()->query($query);
|
$query = "SELECT id, user_id, name, comment FROM " . self::db()->table('tracks') . " WHERE id = ? LIMIT 1";
|
||||||
$trackArr = [];
|
$stmt = self::db()->prepare($query);
|
||||||
while ($row = $result->fetch()) {
|
$stmt->execute([$trackId]);
|
||||||
$trackArr[] = self::rowToObject($row);
|
$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) {
|
} catch (PDOException $e) {
|
||||||
// TODO: handle exception
|
// TODO: handle exception
|
||||||
syslog(LOG_ERR, $e->getMessage());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
@ -61,20 +61,20 @@ class uUpload {
|
|||||||
/**
|
/**
|
||||||
* Get file extension for given mime
|
* Get file extension for given mime
|
||||||
* @param $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) {
|
private static function getExtension($mime) {
|
||||||
if (self::isKnownMime($mime)) {
|
if (self::isKnownMime($mime)) {
|
||||||
return self::getMimeMap()[$mime];
|
return self::getMimeMap()[$mime];
|
||||||
}
|
}
|
||||||
return NULL;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save file to uploads, basic sanitizing
|
* Save file to uploads, basic sanitizing
|
||||||
* @param array $uploaded File meta array from $_FILES[]
|
* @param array $uploaded File meta array from $_FILES[]
|
||||||
* @param int $trackId
|
* @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) {
|
public static function add($uploaded, $trackId) {
|
||||||
try {
|
try {
|
||||||
@ -82,7 +82,7 @@ class uUpload {
|
|||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
syslog(LOG_ERR, $e->getMessage());
|
syslog(LOG_ERR, $e->getMessage());
|
||||||
// save exception to txt file as image replacement?
|
// save exception to txt file as image replacement?
|
||||||
return NULL;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$extension = self::getExtension($fileMeta[self::META_TYPE]);
|
$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)) {
|
if (move_uploaded_file($fileMeta[self::META_TMP_NAME], self::$uploadDir . $fileName)) {
|
||||||
return $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_CANT_WRITE] = "Failed to write file to disk";
|
||||||
$uploadErrors[UPLOAD_ERR_EXTENSION] = "A PHP extension stopped file upload";
|
$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;
|
$fileError = isset($fileMeta[self::META_ERROR]) ? $fileMeta[self::META_ERROR] : UPLOAD_ERR_OK;
|
||||||
if ($fileMeta[self::META_SIZE] > uUtils::getSystemUploadLimit() && $fileError == UPLOAD_ERR_OK) {
|
if ($fileMeta[self::META_SIZE] > uUtils::getSystemUploadLimit() && $fileError == UPLOAD_ERR_OK) {
|
||||||
$fileError = UPLOAD_ERR_FORM_SIZE;
|
$fileError = UPLOAD_ERR_FORM_SIZE;
|
||||||
|
416
helpers/user.php
416
helpers/user.php
@ -20,222 +20,222 @@
|
|||||||
require_once(ROOT_DIR . "/helpers/track.php");
|
require_once(ROOT_DIR . "/helpers/track.php");
|
||||||
require_once(ROOT_DIR . "/helpers/position.php");
|
require_once(ROOT_DIR . "/helpers/position.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User handling routines
|
* User handling routines
|
||||||
*/
|
*/
|
||||||
class uUser {
|
class uUser {
|
||||||
public $id;
|
public $id;
|
||||||
public $login;
|
public $login;
|
||||||
public $hash;
|
public $hash;
|
||||||
public $isAdmin = false;
|
public $isAdmin = false;
|
||||||
public $isValid = false;
|
public $isValid = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
* @param string $login Login
|
* @param string $login Login
|
||||||
*/
|
*/
|
||||||
public function __construct($login = NULL) {
|
public function __construct($login = null) {
|
||||||
if (!empty($login)) {
|
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;
|
|
||||||
try {
|
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 = self::db()->prepare($query);
|
||||||
$stmt->execute([ (int) $isAdmin, $this->login ]);
|
$stmt->execute([ $login ]);
|
||||||
$ret = true;
|
$stmt->bindColumn('id', $this->id, PDO::PARAM_INT);
|
||||||
$this->isAdmin = $isAdmin;
|
$stmt->bindColumn('login', $this->login);
|
||||||
} catch (PDOException $e) {
|
$stmt->bindColumn('password', $this->hash);
|
||||||
// TODO: handle exception
|
$stmt->bindColumn('admin', $this->isAdmin, PDO::PARAM_BOOL);
|
||||||
syslog(LOG_ERR, $e->getMessage());
|
if ($stmt->fetch(PDO::FETCH_BOUND)) {
|
||||||
}
|
$this->isValid = true;
|
||||||
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) {
|
} catch (PDOException $e) {
|
||||||
// TODO: handle exception
|
// TODO: handle exception
|
||||||
syslog(LOG_ERR, $e->getMessage());
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -17,211 +17,211 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Various util functions
|
* Various util functions
|
||||||
*/
|
*/
|
||||||
class uUtils {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
44
index.php
44
index.php
@ -17,32 +17,32 @@
|
|||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once(__DIR__ . '/helpers/auth.php');
|
require_once(__DIR__ . '/helpers/auth.php');
|
||||||
require_once(ROOT_DIR . '/helpers/config.php');
|
require_once(ROOT_DIR . '/helpers/config.php');
|
||||||
require_once(ROOT_DIR . '/helpers/position.php');
|
require_once(ROOT_DIR . '/helpers/position.php');
|
||||||
require_once(ROOT_DIR . '/helpers/track.php');
|
require_once(ROOT_DIR . '/helpers/track.php');
|
||||||
require_once(ROOT_DIR . '/helpers/utils.php');
|
require_once(ROOT_DIR . '/helpers/utils.php');
|
||||||
require_once(ROOT_DIR . '/helpers/lang.php');
|
require_once(ROOT_DIR . '/helpers/lang.php');
|
||||||
|
|
||||||
$login = uUtils::postString('user');
|
$login = uUtils::postString('user');
|
||||||
$pass = uUtils::postPass('pass');
|
$pass = uUtils::postPass('pass');
|
||||||
$action = uUtils::postString('action');
|
$action = uUtils::postString('action');
|
||||||
|
|
||||||
$config = uConfig::getInstance();
|
$config = uConfig::getInstance();
|
||||||
$lang = (new uLang($config))->getStrings();
|
$lang = (new uLang($config))->getStrings();
|
||||||
$langsArr = uLang::getLanguages();
|
$langsArr = uLang::getLanguages();
|
||||||
|
|
||||||
$auth = new uAuth();
|
$auth = new uAuth();
|
||||||
if ($action === 'auth') {
|
if ($action === 'auth') {
|
||||||
$auth->checkLogin($login, $pass);
|
$auth->checkLogin($login, $pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($action === 'auth' && !$auth->isAuthenticated()) {
|
if ($action === 'auth' && !$auth->isAuthenticated()) {
|
||||||
$auth->exitWithRedirect('login.php?auth_error=1');
|
$auth->exitWithRedirect('login.php?auth_error=1');
|
||||||
}
|
}
|
||||||
if ($config->requireAuthentication && !$auth->isAuthenticated()) {
|
if ($config->requireAuthentication && !$auth->isAuthenticated()) {
|
||||||
$auth->exitWithRedirect('login.php');
|
$auth->exitWithRedirect('login.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
|
@ -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>
|
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>
|
<div style="clear: both; padding-bottom: 1em;"></div>
|
||||||
<form id="configForm">
|
<form id="config-form">
|
||||||
<label><b>${$._('language')}</b>
|
<label><b>${$._('language')}</b>
|
||||||
<select data-bind="lang">
|
<select data-bind="lang">
|
||||||
${langOptions}
|
${langOptions}
|
||||||
|
@ -138,7 +138,7 @@ foreach ($gpxFiles as $i => $gpxFile) {
|
|||||||
$trackCnt = 0;
|
$trackCnt = 0;
|
||||||
foreach ($gpx->trk as $trk) {
|
foreach ($gpx->trk as $trk) {
|
||||||
$trackName = empty($trk->name) ? $gpxName : (string) $trk->name;
|
$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);
|
$trackId = uTrack::add($userId, $trackName, $metaName);
|
||||||
if ($trackId === false) {
|
if ($trackId === false) {
|
||||||
uUtils::exitWithError($lang["servererror"]);
|
uUtils::exitWithError($lang["servererror"]);
|
||||||
@ -154,10 +154,10 @@ foreach ($gpxFiles as $i => $gpxFile) {
|
|||||||
uUtils::exitWithError($lang["iparsefailure"]);
|
uUtils::exitWithError($lang["iparsefailure"]);
|
||||||
}
|
}
|
||||||
$time = isset($point->time) ? strtotime($point->time) : 0;
|
$time = isset($point->time) ? strtotime($point->time) : 0;
|
||||||
$altitude = isset($point->ele) ? (double) $point->ele : NULL;
|
$altitude = isset($point->ele) ? (double) $point->ele : null;
|
||||||
$speed = NULL;
|
$speed = null;
|
||||||
$bearing = NULL;
|
$bearing = null;
|
||||||
$accuracy = NULL;
|
$accuracy = null;
|
||||||
$provider = "gps";
|
$provider = "gps";
|
||||||
if (!empty($point->extensions)) {
|
if (!empty($point->extensions)) {
|
||||||
// parse ulogger extensions
|
// parse ulogger extensions
|
||||||
@ -169,7 +169,7 @@ foreach ($gpxFiles as $i => $gpxFile) {
|
|||||||
}
|
}
|
||||||
$ret = $track->addPosition($userId,
|
$ret = $track->addPosition($userId,
|
||||||
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
|
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
|
||||||
$speed, $bearing, $accuracy, $provider, NULL, NULL);
|
$speed, $bearing, $accuracy, $provider, null, null);
|
||||||
if ($ret === false) {
|
if ($ret === false) {
|
||||||
$track->delete();
|
$track->delete();
|
||||||
uUtils::exitWithError($lang["servererror"]);
|
uUtils::exitWithError($lang["servererror"]);
|
||||||
|
@ -100,8 +100,8 @@ if ($trackId && $userId) {
|
|||||||
$xml->setIndent(true);
|
$xml->setIndent(true);
|
||||||
$xml->startDocument("1.0", "utf-8");
|
$xml->startDocument("1.0", "utf-8");
|
||||||
$xml->startElement("kml");
|
$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("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("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
|
||||||
$xml->writeAttribute("xmlns", "http://www.opengis.net/kml/2.2");
|
$xml->writeAttribute("xmlns", "http://www.opengis.net/kml/2.2");
|
||||||
$xml->startElement("Document");
|
$xml->startElement("Document");
|
||||||
$xml->writeElement("name", $positionsArr[0]->trackName);
|
$xml->writeElement("name", $positionsArr[0]->trackName);
|
||||||
@ -132,7 +132,7 @@ if ($trackId && $userId) {
|
|||||||
if(++$i === count($positionsArr)) { $style = "#greenStyle"; } // last element
|
if(++$i === count($positionsArr)) { $style = "#greenStyle"; } // last element
|
||||||
$xml->startElement("Placemark");
|
$xml->startElement("Placemark");
|
||||||
$xml->writeAttribute("id", "point_{$position->id}");
|
$xml->writeAttribute("id", "point_{$position->id}");
|
||||||
$description =
|
$description =
|
||||||
"<div style=\"font-weight: bolder; padding-bottom: 10px; border-bottom: 1px solid gray;\">" .
|
"<div style=\"font-weight: bolder; padding-bottom: 10px; border-bottom: 1px solid gray;\">" .
|
||||||
"{$lang["user"]}: " . htmlspecialchars($position->userLogin) . "<br>{$lang["track"]}: " . htmlspecialchars($position->trackName) .
|
"{$lang["user"]}: " . htmlspecialchars($position->userLogin) . "<br>{$lang["track"]}: " . htmlspecialchars($position->trackName) .
|
||||||
"</div>" .
|
"</div>" .
|
||||||
@ -151,7 +151,7 @@ if ($trackId && $userId) {
|
|||||||
$xml->endElement();
|
$xml->endElement();
|
||||||
$xml->writeElement("styleUrl", $style);
|
$xml->writeElement("styleUrl", $style);
|
||||||
$xml->startElement("Point");
|
$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->writeElement("coordinates", $coordinate[$i]);
|
||||||
$xml->endElement();
|
$xml->endElement();
|
||||||
$xml->endElement();
|
$xml->endElement();
|
||||||
@ -182,9 +182,9 @@ if ($trackId && $userId) {
|
|||||||
$xml->startDocument("1.0", "utf-8");
|
$xml->startDocument("1.0", "utf-8");
|
||||||
$xml->startElement("gpx");
|
$xml->startElement("gpx");
|
||||||
$xml->writeAttribute("xmlns", "http://www.topografix.com/GPX/1/1");
|
$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("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", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
|
||||||
$xml->writeAttributeNs("xmlns", "ulogger", NULL, "https://github.com/bfabiszewski/ulogger-android/1");
|
$xml->writeAttributeNs("xmlns", "ulogger", null, "https://github.com/bfabiszewski/ulogger-android/1");
|
||||||
$xml->writeAttribute("creator", "μlogger-server " . $config->version);
|
$xml->writeAttribute("creator", "μlogger-server " . $config->version);
|
||||||
$xml->writeAttribute("version", "1.1");
|
$xml->writeAttribute("version", "1.1");
|
||||||
$xml->startElement("metadata");
|
$xml->startElement("metadata");
|
||||||
@ -194,46 +194,47 @@ if ($trackId && $userId) {
|
|||||||
$xml->startElement("trk");
|
$xml->startElement("trk");
|
||||||
$xml->writeElement("name", $positionsArr[0]->trackName);
|
$xml->writeElement("name", $positionsArr[0]->trackName);
|
||||||
$xml->startElement("trkseg");
|
$xml->startElement("trkseg");
|
||||||
$i = 0;
|
$i = 0;
|
||||||
$totalMeters = 0;
|
$totalMeters = 0;
|
||||||
$totalSeconds = 0;
|
$totalSeconds = 0;
|
||||||
foreach ($positionsArr as $position) {
|
foreach ($positionsArr as $position) {
|
||||||
$distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0;
|
$distance = isset($prevPosition) ? $position->distanceTo($prevPosition) : 0;
|
||||||
$seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0;
|
$seconds = isset($prevPosition) ? $position->secondsTo($prevPosition) : 0;
|
||||||
$prevPosition = $position;
|
$prevPosition = $position;
|
||||||
$totalMeters += $distance;
|
$totalMeters += $distance;
|
||||||
$totalSeconds += $seconds;
|
$totalSeconds += $seconds;
|
||||||
$xml->startElement("trkpt");
|
$xml->startElement("trkpt");
|
||||||
$xml->writeAttribute("lat", $position->latitude);
|
$xml->writeAttribute("lat", $position->latitude);
|
||||||
$xml->writeAttribute("lon", $position->longitude);
|
$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("time", gmdate("Y-m-d\TH:i:s\Z", $position->timestamp));
|
||||||
$xml->writeElement("name", ++$i);
|
$xml->writeElement("name", ++$i);
|
||||||
if (!is_null($position->comment)) {
|
if (!is_null($position->comment)) {
|
||||||
$xml->startElement("desc");
|
$xml->startElement("desc");
|
||||||
$xml->writeCData($position->comment);
|
$xml->writeCData($position->comment);
|
||||||
$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();
|
|
||||||
}
|
}
|
||||||
|
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();
|
$xml->endElement();
|
||||||
$xml->endElement();
|
$xml->endElement();
|
||||||
|
@ -41,7 +41,7 @@ if ($admin && !$auth->isAdmin()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$aUser = new uUser($login);
|
$aUser = new uUser($login);
|
||||||
$data = NULL;
|
$data = null;
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
case 'add':
|
case 'add':
|
||||||
|
@ -73,7 +73,7 @@ else if (empty($gpx->trk)) {
|
|||||||
$trackList = [];
|
$trackList = [];
|
||||||
foreach ($gpx->trk as $trk) {
|
foreach ($gpx->trk as $trk) {
|
||||||
$trackName = empty($trk->name) ? $gpxName : (string) $trk->name;
|
$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);
|
$trackId = uTrack::add($auth->user->id, $trackName, $metaName);
|
||||||
if ($trackId === false) {
|
if ($trackId === false) {
|
||||||
uUtils::exitWithError($lang["servererror"]);
|
uUtils::exitWithError($lang["servererror"]);
|
||||||
@ -89,11 +89,11 @@ foreach ($gpx->trk as $trk) {
|
|||||||
uUtils::exitWithError($lang["iparsefailure"]);
|
uUtils::exitWithError($lang["iparsefailure"]);
|
||||||
}
|
}
|
||||||
$time = isset($point->time) ? strtotime($point->time) : 1;
|
$time = isset($point->time) ? strtotime($point->time) : 1;
|
||||||
$altitude = isset($point->ele) ? (double) $point->ele : NULL;
|
$altitude = isset($point->ele) ? (double) $point->ele : null;
|
||||||
$comment = isset($point->desc) && !empty($point->desc) ? (string) $point->desc : NULL;
|
$comment = isset($point->desc) && !empty($point->desc) ? (string) $point->desc : null;
|
||||||
$speed = NULL;
|
$speed = null;
|
||||||
$bearing = NULL;
|
$bearing = null;
|
||||||
$accuracy = NULL;
|
$accuracy = null;
|
||||||
$provider = "gps";
|
$provider = "gps";
|
||||||
if (!empty($point->extensions)) {
|
if (!empty($point->extensions)) {
|
||||||
// parse ulogger extensions
|
// parse ulogger extensions
|
||||||
@ -105,7 +105,7 @@ foreach ($gpx->trk as $trk) {
|
|||||||
}
|
}
|
||||||
$ret = $track->addPosition($auth->user->id,
|
$ret = $track->addPosition($auth->user->id,
|
||||||
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
|
$time, (double) $point["lat"], (double) $point["lon"], $altitude,
|
||||||
$speed, $bearing, $accuracy, $provider, $comment, NULL);
|
$speed, $bearing, $accuracy, $provider, $comment, null);
|
||||||
if ($ret === false) {
|
if ($ret === false) {
|
||||||
$track->delete();
|
$track->delete();
|
||||||
uUtils::exitWithError($lang["servererror"]);
|
uUtils::exitWithError($lang["servererror"]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user