value = $value; } function getValue() { return $this->value; } } class RemoteDate extends RemoteDataType {} class RemoteFile extends RemoteDataType {} /** * This class provides information about remote access to the wiki. * * == Types of methods == * There are two types of remote methods. The first is the core methods. * These are always available and provided by dokuwiki. * The other is plugin methods. These are provided by remote plugins. * * == Information structure == * The information about methods will be given in an array with the following structure: * array( * 'method.remoteName' => array( * 'args' => array( * 'name' => 'type eg. string|int|...|date|file', * ) * 'name' => 'method name in class', * 'return' => 'type', * ['doc' = 'method documentation'], * ) * ) * * plugin names are formed the following: * core methods begin by a 'dokuwiki' or 'wiki' followed by a . and the method name itself. * i.e.: dokuwiki.version or wiki.getPage * * plugin methods are formed like 'plugin..'. * i.e.: plugin.clock.getTime or plugin.clock_gmt.getTime * * * * @throws RemoteException */ class RemoteAPI { /** * @var RemoteAPICore */ private $coreMethods = null; /** * @var array remote methods provided by dokuwiki plugins - will be filled lazy via * {@see RemoteAPI#getPluginMethods} */ private $pluginMethods = null; /** * Get all available methods with remote access. * * @return array with information to all available methods */ public function getMethods() { return array_merge($this->getCoreMethods(), $this->getPluginMethods()); } /** * call a method via remote api. * * @param string $method name of the method to call. * @param array $args arguments to pass to the given method * @return mixed result of method call, must be a primitive type. */ public function call($method, $args = array()) { list($type, $pluginName, $call) = explode('.', $method, 3); if ($type === 'plugin') { $plugin = plugin_load('remote', $pluginName); $methods = $this->getPluginMethods(); if (!$plugin) { throw new RemoteException('Method dose not exists'); } $this->checkAccess($methods[$method]); $name = $this->getMethodName($methods, $method); return call_user_func_array(array($plugin, $name), $args); } else { $coreMethods = $this->getCoreMethods(); $this->checkAccess($coreMethods[$method]); if (!isset($coreMethods[$method])) { throw new RemoteException('Method dose not exists'); } $this->checkArgumentLength($coreMethods[$method], $args); return call_user_func_array(array($this->coreMethods, $this->getMethodName($coreMethods, $method)), $args); } } private function checkAccess($methodMeta) { if (!isset($methodMeta['public'])) { $this->forceAccess(); } else{ if ($methodMeta['public'] == '0') { $this->forceAccess(); } } } private function checkArgumentLength($method, $args) { if (count($method['args']) < count($args)) { throw new RemoteException('Method dose not exists - wrong parameter count.'); } } private function getMethodName($methodMeta, $method) { if (isset($methodMeta[$method]['name'])) { return $methodMeta[$method]['name']; } $method = explode('.', $method); return $method[count($method)-1]; } /** * @return bool true if the current user has access to remote api. */ public function hasAccess() { global $conf; global $USERINFO; if (!$conf['remote']) { return false; } if(!$conf['useacl']) { return true; } if(trim($conf['remoteuser']) == '') { return true; } return auth_isMember($conf['remoteuser'], $_SERVER['REMOTE_USER'], (array) $USERINFO['grps']); } /** * @throws RemoteException On denied access. * @return void */ public function forceAccess() { if (!$this->hasAccess()) { throw new RemoteAccessDenied(); } } /** * @return array all plugin methods. */ public function getPluginMethods() { if ($this->pluginMethods === null) { $this->pluginMethods = array(); $plugins = plugin_list('remote'); foreach ($plugins as $pluginName) { $plugin = plugin_load('remote', $pluginName); if (!is_subclass_of($plugin, 'DokuWiki_Remote_Plugin')) { throw new RemoteException("Plugin $pluginName dose not implement DokuWiki_Remote_Plugin"); } $methods = $plugin->_getMethods(); foreach ($methods as $method => $meta) { $this->pluginMethods["plugin.$pluginName.$method"] = $meta; } } } return $this->pluginMethods; } /** * @param RemoteAPICore $apiCore this parameter is used for testing. Here you can pass a non-default RemoteAPICore * instance. (for mocking) * @return array all core methods. */ public function getCoreMethods($apiCore = null) { if ($this->coreMethods === null) { if ($apiCore === null) { $this->coreMethods = new RemoteAPICore(); } else { $this->coreMethods = $apiCore; } } return $this->coreMethods->__getRemoteInfo(); } }