xref: /dokuwiki/inc/Remote/JsonRpcServer.php (revision 87603a0ae6bb5f9492d204f5b6cdd611ac4bc13a)
1<?php
2
3namespace dokuwiki\Remote;
4
5/**
6 * Provide the Remote XMLRPC API as a JSON based API
7 */
8class JsonRpcServer
9{
10
11    protected $remote;
12
13    /**
14     * JsonRpcServer constructor.
15     */
16    public function __construct()
17    {
18        $this->remote = new Api();
19        $this->remote->setFileTransformation(array($this, 'toFile'));
20    }
21
22    /**
23     * Serve the request
24     *
25     * @return mixed
26     * @throws RemoteException
27     */
28    public function serve()
29    {
30        global $conf;
31        global $INPUT;
32
33        if (!$conf['remote']) {
34            http_status(404);
35            throw new RemoteException("JSON-RPC server not enabled.", -32605);
36        }
37        if (!empty($conf['remotecors'])) {
38            header('Access-Control-Allow-Origin: ' . $conf['remotecors']);
39        }
40        if ($INPUT->server->str('REQUEST_METHOD') !== 'POST') {
41            http_status(405);
42            header('Allow: POST');
43            throw new RemoteException("JSON-RPC server only accepts POST requests.", -32606);
44        }
45        if ($INPUT->server->str('CONTENT_TYPE') !== 'application/json') {
46            http_status(415);
47            throw new RemoteException("JSON-RPC server only accepts application/json requests.", -32606);
48        }
49
50        $call = $INPUT->server->str('PATH_INFO');
51        $call = trim($call, '/');
52        try {
53            $args = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR);
54        } catch (\Exception $e) {
55            $args = [];
56        }
57        if (!is_array($args)) $args = [];
58
59        return $this->call($call, $args);
60    }
61
62    /**
63     * Call an API method
64     *
65     * @param string $methodname
66     * @param array $args
67     * @return mixed
68     * @throws RemoteException
69     */
70    public function call($methodname, $args)
71    {
72        try {
73            $result = $this->remote->call($methodname, $args);
74            return $result;
75        } catch (AccessDeniedException $e) {
76            if (!isset($_SERVER['REMOTE_USER'])) {
77                http_status(401);
78                throw new RemoteException("server error. not authorized to call method $methodname", -32603);
79            } else {
80                http_status(403);
81                throw new RemoteException("server error. forbidden to call the method $methodname", -32604);
82            }
83        } catch (RemoteException $e) {
84            http_status(400);
85            throw $e;
86        }
87    }
88
89    /**
90     * @param string $data
91     * @return string
92     */
93    public function toFile($data)
94    {
95        return base64_encode($data);
96    }
97
98}
99