diff options
author | Andreas Gohr <andi@splitbrain.org> | 2023-11-28 14:21:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-28 14:21:04 +0100 |
commit | a70eeb2fdfb52b8176f74311df270ce431b54bff (patch) | |
tree | 20f42e8ce50642afc4465590eb847c890c9d8235 | |
parent | d03efe743b065f0a47fa4fc29f640c0f4f814f52 (diff) | |
parent | 8fae2e993b23f293b26b9cd4fd3585c9bcdb4dc1 (diff) | |
download | dokuwiki-a70eeb2fdfb52b8176f74311df270ce431b54bff.tar.gz dokuwiki-a70eeb2fdfb52b8176f74311df270ce431b54bff.zip |
Merge pull request #3961 from dokuwiki/jsonrpc
Add JSON based alternative to XMLRPC
-rw-r--r-- | inc/Remote/Api.php | 6 | ||||
-rw-r--r-- | inc/Remote/JsonRpcServer.php | 94 | ||||
-rw-r--r-- | lib/exe/jsonrpc.php | 31 |
3 files changed, 130 insertions, 1 deletions
diff --git a/inc/Remote/Api.php b/inc/Remote/Api.php index 8e1c8035f..2555157af 100644 --- a/inc/Remote/Api.php +++ b/inc/Remote/Api.php @@ -276,7 +276,11 @@ class Api return true; } - return auth_isMember($conf['remoteuser'], $INPUT->server->str('REMOTE_USER'), (array) $USERINFO['grps']); + return auth_isMember( + $conf['remoteuser'], + $INPUT->server->str('REMOTE_USER'), + (array)($USERINFO['grps'] ?? []) + ); } /** diff --git a/inc/Remote/JsonRpcServer.php b/inc/Remote/JsonRpcServer.php new file mode 100644 index 000000000..1dd518c78 --- /dev/null +++ b/inc/Remote/JsonRpcServer.php @@ -0,0 +1,94 @@ +<?php + +namespace dokuwiki\Remote; + +/** + * Provide the Remote XMLRPC API as a JSON based API + */ +class JsonRpcServer +{ + + protected $remote; + + /** + * JsonRpcServer constructor. + */ + public function __construct() + { + $this->remote = new Api(); + $this->remote->setFileTransformation(array($this, 'toFile')); + } + + /** + * Serve the request + * + * @return mixed + * @throws RemoteException + */ + public function serve() + { + global $conf; + global $INPUT; + + if (!$conf['remote']) { + http_status(404); + throw new RemoteException("JSON-RPC server not enabled.", -32605); + } + if (!empty($conf['remotecors'])) { + header('Access-Control-Allow-Origin: ' . $conf['remotecors']); + } + if ($INPUT->server->str('REQUEST_METHOD') !== 'POST') { + http_status(405); + header('Allow: POST'); + throw new RemoteException("JSON-RPC server only accepts POST requests.", -32606); + } + if ($INPUT->server->str('CONTENT_TYPE') !== 'application/json') { + http_status(415); + throw new RemoteException("JSON-RPC server only accepts application/json requests.", -32606); + } + + $call = $INPUT->server->str('PATH_INFO'); + $call = trim($call, '/'); + $args = json_decode(file_get_contents('php://input'), true); + if (!is_array($args)) $args = []; + + return $this->call($call, $args); + } + + /** + * Call an API method + * + * @param string $methodname + * @param array $args + * @return mixed + * @throws RemoteException + */ + public function call($methodname, $args) + { + try { + $result = $this->remote->call($methodname, $args); + return $result; + } catch (AccessDeniedException $e) { + if (!isset($_SERVER['REMOTE_USER'])) { + http_status(401); + throw new RemoteException("server error. not authorized to call method $methodname", -32603); + } else { + http_status(403); + throw new RemoteException("server error. forbidden to call the method $methodname", -32604); + } + } catch (RemoteException $e) { + http_status(400); + throw $e; + } + } + + /** + * @param string $data + * @return string + */ + public function toFile($data) + { + return base64_encode($data); + } + +} diff --git a/lib/exe/jsonrpc.php b/lib/exe/jsonrpc.php new file mode 100644 index 000000000..3852e2b45 --- /dev/null +++ b/lib/exe/jsonrpc.php @@ -0,0 +1,31 @@ +<?php + +use dokuwiki\Remote\JsonRpcServer; + +if (!defined('DOKU_INC')) define('DOKU_INC', __DIR__ . '/../../'); + +require_once(DOKU_INC . 'inc/init.php'); +session_write_close(); //close session + +header('Content-Type: application/json'); + +$server = new JsonRpcServer(); +try { + $result = [ + 'error' => [ + 'code' => 0, + 'message' => 'success' + ], + 'data' => $server->serve(), + ]; +} catch (\Exception $e) { + $result = [ + 'error' => [ + 'code' => $e->getCode(), + 'message' => $e->getMessage() + ], + 'data' => null, + ]; +} + +echo json_encode($result); |