. */ require_once(ROOT_DIR . "/helpers/db.php"); require_once(ROOT_DIR . "/helpers/layer.php"); /** * Handles config values */ class uConfig { /** * Singleton instance * * @var uConfig Object instance */ private static $instance; /** * @var string Version number */ public $version = "1.0-beta"; /** * @var string Default map drawing framework */ public $mapApi = "openlayers"; /** * @var string|null Google maps key */ public $googleKey; /** * @var uLayer[] Openlayers extra map layers */ public $olLayers = []; /** * @var float Default latitude for initial map */ public $initLatitude = 52.23; /** * @var float Default longitude for initial map */ public $initLongitude = 21.01; /** * @var bool Require login/password authentication */ public $requireAuthentication = true; /** * @var bool All users tracks are visible to authenticated user */ public $publicTracks = false; /** * @var int Miniumum required length of user password */ public $passLenMin = 10; /** * @var int Required strength of user password * 0 = no requirements, * 1 = require mixed case letters (lower and upper), * 2 = require mixed case and numbers * 3 = require mixed case, numbers and non-alphanumeric characters */ public $passStrength = 2; /** * @var int Default interval in seconds for live auto reload */ public $interval = 10; /** * @var string Default language code */ public $lang = "en"; /** * @var string Default units */ public $units = "metric"; /** * @var int Stroke weight */ public $strokeWeight = 2; /** * @var string Stroke color */ public $strokeColor = "#ff0000"; /** * @var float Stroke opacity */ public $strokeOpacity = 1.0; /** * @var string Stroke color */ public $colorNormal = "#ffffff"; /** * @var string Stroke color */ public $colorStart = "#55b500"; /** * @var string Stroke color */ public $colorStop = "#ff6a00"; /** * @var string Stroke color */ public $colorExtra = "#cccccc"; /** * @var string Stroke color */ public $colorHilite = "#feff6a"; /** * @var int Maximum size of uploaded files in bytes. * Will be adjusted to system maximum upload size */ public $uploadMaxSize = 5242880; public function __construct($useDatabase = true) { if ($useDatabase) { $this->setFromDatabase(); } $this->setFromCookies(); } /** * Returns singleton instance * * @return uConfig Singleton instance */ public static function getInstance() { if (!self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Returns singleton instance * * @return uConfig Singleton instance */ public static function getOfflineInstance() { if (!self::$instance) { self::$instance = new self(false); } return self::$instance; } /** * Get db instance * * @return uDb instance */ private static function db() { return uDb::getInstance(); } /** * Read config values from database */ public function setFromDatabase() { try { $query = "SELECT name, value FROM " . self::db()->table("config"); $result = self::db()->query($query); $arr = $result->fetchAll(PDO::FETCH_KEY_PAIR); $this->setFromArray(array_map([ $this, "unserialize" ], $arr)); $this->setLayersFromDatabase(); if (!$this->requireAuthentication) { // tracks must be public if we don't require authentication $this->publicTracks = true; } } catch (PDOException $e) { // TODO: handle exception syslog(LOG_ERR, $e->getMessage()); } } /** * Unserialize data from database * @param string|resource $data Resource returned by pgsql, string otherwise * @return mixed */ private function unserialize($data) { if (is_resource($data)) { return unserialize(stream_get_contents($data)); } return unserialize($data); } /** * Save config values to database * @return bool True on success, false otherwise */ public function save() { $ret = false; try { // PDO::PARAM_LOB doesn't work here with pgsql, why? $placeholder = self::db()->lobPlaceholder(); $values = [ ["'color_extra'", $placeholder], ["'color_hilite'", $placeholder], ["'color_normal'", $placeholder], ["'color_start'", $placeholder], ["'color_stop'", $placeholder], ["'google_key'", $placeholder], ["'latitude'", $placeholder], ["'longitude'", $placeholder], ["'interval_seconds'", $placeholder], ["'lang'", $placeholder], ["'map_api'", $placeholder], ["'pass_lenmin'", $placeholder], ["'pass_strength'", $placeholder], ["'public_tracks'", $placeholder], ["'require_auth'", $placeholder], ["'stroke_color'", $placeholder], ["'stroke_opacity'", $placeholder], ["'stroke_weight'", $placeholder], ["'units'", $placeholder], ["'upload_maxsize'", $placeholder] ]; $query = self::db()->insertOrReplace("config", [ "name", "value" ], $values, "name", "value"); $stmt = self::db()->prepare($query); $params = [ $this->colorExtra, $this->colorHilite, $this->colorNormal, $this->colorStart, $this->colorStop, $this->googleKey, $this->initLatitude, $this->initLongitude, $this->interval, $this->lang, $this->mapApi, $this->passLenMin, $this->passStrength, $this->publicTracks, $this->requireAuthentication, $this->strokeColor, $this->strokeOpacity, $this->strokeWeight, $this->units, $this->uploadMaxSize ]; $stmt->execute(array_map("serialize", $params)); $this->saveLayers(); $ret = true; } catch (PDOException $e) { // TODO: handle exception syslog(LOG_ERR, $e->getMessage()); } return $ret; } /** * Truncate ol_layers table * @throws PDOException */ private function deleteLayers() { $query = "DELETE FROM " . self::db()->table("ol_layers"); self::db()->exec($query); } /** * Save layers to database * @throws PDOException */ private function saveLayers() { $this->deleteLayers(); if (!empty($this->olLayers)) { $query = "INSERT INTO " . self::db()->table("ol_layers") . " (id, name, url, priority) VALUES (?, ?, ?, ?)"; $stmt = self::db()->prepare($query); foreach ($this->olLayers as $layer) { $stmt->execute([ $layer->id, $layer->name, $layer->url, $layer->priority]); } } } /** * Read config values from database * @throws PDOException */ private function setLayersFromDatabase() { $this->olLayers = []; $query = "SELECT id, name, url, priority FROM " . self::db()->table('ol_layers'); $result = self::db()->query($query); while ($row = $result->fetch()) { $this->olLayers[] = new uLayer($row["id"], $row["name"], $row["url"], $row["priority"]); } } /** * Read config values stored in cookies */ private function setFromCookies() { if (isset($_COOKIE["ulogger_api"])) { $this->mapApi = $_COOKIE["ulogger_api"]; } if (isset($_COOKIE["ulogger_lang"])) { $this->lang = $_COOKIE["ulogger_lang"]; } if (isset($_COOKIE["ulogger_units"])) { $this->units = $_COOKIE["ulogger_units"]; } if (isset($_COOKIE["ulogger_interval"])) { $this->interval = $_COOKIE["ulogger_interval"]; } } /** * Check if given password matches user's one * * @param String $password Password * @return bool True if matches, false otherwise */ public function validPassStrength($password) { return preg_match($this->passRegex(), $password); } /** * Regex to test if password matches strength and length requirements. * Valid for both php and javascript * @return string */ public function passRegex() { $regex = ""; if ($this->passStrength > 0) { // lower and upper case $regex .= "(?=.*[a-z])(?=.*[A-Z])"; } if ($this->passStrength > 1) { // digits $regex .= "(?=.*[0-9])"; } if ($this->passStrength > 2) { // not latin, not digits $regex .= "(?=.*[^a-zA-Z0-9])"; } if ($this->passLenMin > 0) { $regex .= "(?=.{" . $this->passLenMin . ",})"; } if (empty($regex)) { $regex = ".*"; } return "/" . $regex . "/"; } /** * Set config values from array * @param array $arr */ public function setFromArray($arr) { if (!is_array($arr)) { return; } if (isset($arr['map_api']) && !empty($arr['map_api'])) { $this->mapApi = $arr['map_api']; } if (isset($arr['latitude']) && is_numeric($arr['latitude'])) { $this->initLatitude = (float) $arr['latitude']; } if (isset($arr['longitude']) && is_numeric($arr['longitude'])) { $this->initLongitude = (float) $arr['longitude']; } if (isset($arr['google_key']) && !is_null($arr['google_key'])) { $this->googleKey = $arr['google_key']; } if (isset($arr['require_auth']) && (is_numeric($arr['require_auth']) || is_bool($arr['require_auth']))) { $this->requireAuthentication = (bool) $arr['require_auth']; } if (isset($arr['public_tracks']) && (is_numeric($arr['public_tracks']) || is_bool($arr['public_tracks']))) { $this->publicTracks = (bool) $arr['public_tracks']; } if (isset($arr['pass_lenmin']) && is_numeric($arr['pass_lenmin'])) { $this->passLenMin = (int) $arr['pass_lenmin']; } if (isset($arr['pass_strength']) && is_numeric($arr['pass_strength'])) { $this->passStrength = (int) $arr['pass_strength']; } if (isset($arr['interval_seconds']) && is_numeric($arr['interval_seconds'])) { $this->interval = (int) $arr['interval_seconds']; } if (isset($arr['lang']) && !empty($arr['lang'])) { $this->lang = $arr['lang']; } if (isset($arr['units']) && !empty($arr['units'])) { $this->units = $arr['units']; } if (isset($arr['stroke_weight']) && is_numeric($arr['stroke_weight'])) { $this->strokeWeight = (int) $arr['stroke_weight']; } if (isset($arr['stroke_color']) && !empty($arr['stroke_color'])) { $this->strokeColor = $arr['stroke_color']; } if (isset($arr['stroke_opacity']) && is_numeric($arr['stroke_opacity'])) { $this->strokeOpacity = (float) $arr['stroke_opacity']; } if (isset($arr['color_normal']) && !empty($arr['color_normal'])) { $this->colorNormal = $arr['color_normal']; } if (isset($arr['color_start']) && !empty($arr['color_start'])) { $this->colorStart = $arr['color_start']; } if (isset($arr['color_stop']) && !empty($arr['color_stop'])) { $this->colorStop = $arr['color_stop']; } if (isset($arr['color_extra']) && !empty($arr['color_extra'])) { $this->colorExtra = $arr['color_extra']; } if (isset($arr['color_hilite']) && !empty($arr['color_hilite'])) { $this->colorHilite = $arr['color_hilite']; } if (isset($arr['upload_maxsize']) && is_numeric($arr['upload_maxsize'])) { $this->uploadMaxSize = (int) $arr['upload_maxsize']; $this->setUploadLimit(); } } /** * Adjust uploadMaxSize to system limits */ private function setUploadLimit() { $limit = uUtils::getSystemUploadLimit(); if ($this->uploadMaxSize <= 0 || $this->uploadMaxSize > $limit) { $this->uploadMaxSize = $limit; } } } ?>