271 lines
7.2 KiB
PHP
271 lines
7.2 KiB
PHP
<?php
|
|
/**
|
|
* SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* @author Sascha Nitsch (grumpydeveloper)
|
|
**/
|
|
|
|
namespace Federator;
|
|
|
|
/**
|
|
* main API class
|
|
*/
|
|
class Api extends Main
|
|
{
|
|
/**
|
|
* called path
|
|
*
|
|
* @var string $path
|
|
*/
|
|
private $path;
|
|
|
|
/**
|
|
* path elements for the API call
|
|
*
|
|
* @var array<string> $paths
|
|
* */
|
|
private $paths;
|
|
|
|
/**
|
|
* current user
|
|
*
|
|
* @var Data\User|false $user
|
|
* */
|
|
private $user;
|
|
|
|
/**
|
|
* cache time default to 0
|
|
*
|
|
* @var int $cacheTime
|
|
*/
|
|
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
|
|
* @return void
|
|
*/
|
|
public function setPath($call)
|
|
{
|
|
$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((string)$_REQUEST['_call']);
|
|
$this->openDatabase();
|
|
$this->loadPlugins();
|
|
$retval = "";
|
|
$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");
|
|
}
|
|
// @phan-suppress-next-line PhanSuspiciousValueComparison
|
|
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 === false) {
|
|
throw new Exceptions\PermissionDenied();
|
|
}
|
|
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((string)$_POST[$key]));
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* update $data with POST info using optional alias $altName
|
|
*
|
|
* @param string $name
|
|
* parameter name
|
|
* @param array<string, mixed> $data
|
|
* array to update
|
|
* @param bool $int
|
|
* is data an integer
|
|
* @param string $altName
|
|
* optional alternative name in POST
|
|
* @return void
|
|
*/
|
|
public function updateString($name, &$data, $int = false, $altName = "")
|
|
{
|
|
if ($this->hasPost($altName ?: $name)) {
|
|
$content = $this->escapePost($altName ?: $name, $int);
|
|
$data[$name] = $content;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* set cache time
|
|
*
|
|
* @param int $time time in seconds
|
|
* @return void
|
|
*/
|
|
public function setCacheTime($time)
|
|
{
|
|
$this->cacheTime = $time;
|
|
}
|
|
}
|