aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorAndreas Gohr <andi@splitbrain.org>2023-11-28 14:21:04 +0100
committerGitHub <noreply@github.com>2023-11-28 14:21:04 +0100
commita70eeb2fdfb52b8176f74311df270ce431b54bff (patch)
tree20f42e8ce50642afc4465590eb847c890c9d8235
parentd03efe743b065f0a47fa4fc29f640c0f4f814f52 (diff)
parent8fae2e993b23f293b26b9cd4fd3585c9bcdb4dc1 (diff)
downloaddokuwiki-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.php6
-rw-r--r--inc/Remote/JsonRpcServer.php94
-rw-r--r--lib/exe/jsonrpc.php31
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);