252 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
	
		
			7 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
 | 
						|
{
 | 
						|
    /** @var string called path */
 | 
						|
    private $path;
 | 
						|
 | 
						|
    /** @var array<string> 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<string,mixed> $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;
 | 
						|
    }
 | 
						|
}
 |