path elements for the API call */ private $paths; /** @var Data\User current user */ private $user; /** @var int cache time default to 0 */ private $cacheTime = 0; /** * constructor */ public function __construct() { $this->smarty = null; $this->contentType = "application/json"; Main::__construct(); } /** * set path * * @param string $call * path of called function */ public function setPath(string $call) : void { $this->path = $call; while ($this->path[0] === '/') { $this->path = substr($this->path, 1); } $this->paths = explode("/", $this->path); } /** * main API function */ public function run() : void { $this->setPath($_REQUEST["_call"]); $this->openDatabase(); $this->loadPlugins(); $retval = ""; /** @var \Api\Api */ $handler = null; if (!array_key_exists('HTTP_X_SESSION', $_SERVER) || !array_key_exists('HTTP_X_PROFILE', $_SERVER)) { http_response_code(403); return; } if ($this->connector === null) { http_response_code(500); return; } $this->user = DIO\User::getUserBySession( $this->dbh, $_SERVER['HTTP_X_SESSION'], $_SERVER['HTTP_X_PROFILE'], $this->connector, $this->cache ); if ($this->user === false) { http_response_code(403); return; } switch ($this->path[0]) { case 'v': if ($this->paths[0] === "v1") { switch ($this->paths[1]) { case 'dummy': $handler = new Api\V1\Dummy($this); break; } } break; } $printresponse = true; if ($handler !== null) { try { $printresponse = $handler->exec($this->paths); if ($printresponse) { $retval = $handler->toJson(); } } catch (Exceptions\Exception $e) { $this->setResponseCode($e->getRetCode()); $retval = json_encode(array( "error" => $e->getMessage() )); } } else { $this->responseCode = 404; } if (sizeof($this->headers) != 0) { foreach ($this->headers as $name => $value) { header($name . ': ' . $value); } } if ($printresponse) { if ($this->redirect !== null) { header("Location: $this->redirect"); } if ($this->responseCode != 200) { http_response_code($this->responseCode); } if ($this->responseCode != 404) { header("Content-type: " . $this->contentType); header("Access-Control-Allow-Origin: *"); } if ($this->cacheTime == 0) { header("Cache-Control: no-cache, no-store, must-revalidate"); header("Pragma: no-cache"); header("Expires: 0"); } else { $ts = gmdate("D, d M Y H:i:s", time() + $this->cacheTime) . " GMT"; header("Expires: $ts"); header("Pragma: cache"); header("Cache-Control: max-age=" . $this->cacheTime); } echo $retval; } else { if (!headers_sent()) { header("Content-type: " . $this->contentType); } } } /** * check if the current user has the given permission * * @param string|string[] $permission * permission(s) to check for * @param string $exception Exception Type * @param string $message optional message * @throws \Exceptions\PermissionDenied */ public function checkPermission($permission, $exception = "\Exceptions\PermissionDenied", $message = null) : void { // generic check first if ($this->user->id == 0) { throw new Exceptions\PermissionDenied(); } if (!is_array($permission)) { $permission = array( $permission ); } // LoggedIn is handled above foreach ($permission as $p) { if ($this->user->hasPermission($p)) { return; } } throw new $exception($message); } /** * remove unwanted elements from html input * * @param string $_input * input to strip * @return string stripped input */ public static function stripHTML(string $_input) : string { $out = preg_replace('/<(script[^>]*)>/i', '<${1}>', $_input); $out = preg_replace('/<\/(script)>/i', '</${1};>', $out); return $out; } /** * is given parameter in POST data * * @param string $_key * parameter to check * @return bool true if in */ public static function hasPost(string $_key) : bool { return array_key_exists($_key, $_POST); } /** * SQL escape given POST parameter * * @param string $key * key to escape * @param boolean $int * is parameter an int * @return int|string */ public function escapePost(string $key, $int = false) { if (! array_key_exists($key, $_POST)) { return $int ? 0 : ""; } if ($int === true) { return intval($_POST[$key]); } $ret = $this->dbh->escape_string($this->stripHTML($_POST[$key])); if ($ret === false) { return $int ? 0 : ""; } return $ret; } /** * update $data with POST info using optional alias $altName * * @param string $name * parameter name * @param array $data * array to update * @param bool $int * is data an integer * @param string $altName * optional alternative name in POST */ public function updateString(string $name, array &$data, bool $int = false, string $altName = "") : void { if ($this->hasPost($altName ?: $name)) { $content = $this->escapePost($altName ?: $name, $int); $data[$name] = $content; } } /** * set cache time * * @param int $time time in seconds */ public function setCacheTime(int $time) : void { $this->cacheTime = $time; } }