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