* @desc Handle SOAP requests */ /** * Specific handler to gather errors */ class SOAP_errorHandler { var $errors = array(); function __construct() {} function getErrors() { return array_values($this->errors); } } /** * Class that handles SOAP requests */ class farmSOAP { private $server = null; /** * @param $s reference to the SOAP handler */ function __construct($s) { $this->server = $s; } /** * Identify remote application and process SOAP requests * @return array returned from service call */ function authenticateRemoteAppAndRun() { $args = func_get_args(); if(count($args) < 3) return array(); // get call args $appname = $args[0]; $apppwd = $args[1]; $service = $args[2]; if($appname == '' || $apppwd == '' || $service == '') return array(); $serviceargs = isset($args[3]) ? (is_array($args[3]) ? $args[3] : array($args[3])) : array(); // identify app $app = $this->getApp($appname); if(!$app) return array(); if(bin2hex(mhash(1, $apppwd)) != $app['pwd']) return array(); // check rights if(!isset($app['allowed'][$service])) return array(); if(!method_exists($this, 'service_'.$service)) return array(); // call and return foreach($app['allowed'][$service] as $k => $v) { if(is_array($v)) { if(!in_array($serviceargs[$k], $v)) $serviceargs[$k] = reset($v); }else $serviceargs[$k] = $v; } return call_user_func(array($this, 'service_'.$service), $serviceargs); } /** * Check whether an application is in the trust list and gather its rights * @param $name application name * @return application descriptor */ function getApp($name) { foreach(explode("\n\n", preg_replace('`<\?php[^?]+\?>\s*`i', '', file_get_contents('./trusted_apps.php'))) as $a) { $app = array(); foreach(explode("\n", trim($a)) as $f) { if(preg_match('`^(name|pwd)\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) $app[$m[1]] = trim($m[2]); if(preg_match('`^allowed\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) { $app['allowed'] = array(); $list = trim($m[1]); while(preg_match('`^([^(,]+)(\(([^)]+)\))?(\s*,\s*(.*))?$`', $list, $m)) { $sname = trim($m[1]); $ovr = trim($m[3]); $list = isset($m[5]) ? trim($m[5]) : ''; $app['allowed'][$sname] = array(); if($ovr != '') { foreach(array_map('trim', explode(',', $ovr)) as $o) { $o = array_map('trim', explode('=', $o)); if(count($o) == 1) { $app['allowed'][$sname][$o[0]] = true; }elseif(count($o) == 2) { if(preg_match('`^\[[^]]+\]$`', $o[1])) $o[1] = array_map('trim', explode(',', substr($o[1], 1, -1))); elseif(preg_match('`^[0-9]+$`', $o[1])) $o[1] = (int)$o[1]; elseif(preg_match('`^[0-9]+\.[0-9]+$`', $o[1])) $o[1] = (float)$o[1]; elseif(preg_match('`^(true|false)$`i', $o[1])) $o[1] = (strtolower($o[1]) == 'true'); elseif(preg_match('`^null$`i', $o[1])) $o[1] = null; $app['allowed'][$sname][$o[0]] = $o[1]; } } } } } } if(isset($app['name']) && $app['name'] == $name) return $app; } return null; } /* *==========* * SERVICES * *==========* */ /** * Simple service that returns args to check app auth & passed args * @param $args SOAP arguments * @return stuff */ function service_test($args) { return array('appauth' => 'ok', 'args' => $args); } /** * Service that creates an animal * @param $args SOAP arguments * @return success indicator and errors, also contains accepted name if successful (only different from original if it contained funky characters) */ function service_animalCreate($args) { $name = isset($args['name']) ? $args['name'] : ''; $template = isset($args['template']) ? $args['template'] : ''; $host = isset($args['host']) ? $args['host'] : ''; // only used if farm is in virtual mode $eh = new SOAP_errorHandler(); if($n = dokuwiki_farm_animal::createNew($name, $template, $host, $eh)) { return array('success' => true, 'name' => $n); }else return array('success' => false, 'errors' => $eh->getErrors()); } /** * Service that deletes an animal * @param $args SOAP arguments * @return success indicator */ function service_animalDelete($args) { $name = isset($args['name']) ? $args['name'] : reset($args); if(!dokuwiki_farm_animal::exists($name)) return array('success' => false); $a = new dokuwiki_farm_animal($name); return array('success' => $a->delete()); } /** * Service that returns animal's status (existence/state) * @param $args SOAP arguments * @return animal status */ function service_animalExists($args) { $name = isset($args['name']) ? $args['name'] : reset($args); if(!dokuwiki_farm_animal::exists($args['name'])) return array('exists' => 0); $a = new dokuwiki_farm_animal($args['name']); return array( 'exists' => 1, 'status' => $a->getStatus(), 'locked' => $a->getLockState() ); } /** * Service that changes the status of an animal * @param $args SOAP arguments * @return success indicator */ function service_animalStatus($args) { $name = isset($args['name']) ? $args['name'] : ''; $status = isset($args['status']) ? $args['status'] : ''; if($name == '' || in_array($status, array('open', 'maintenance', 'closed', 'abuse'))) return array(); if(!dokuwiki_farm_animal::exists($name)) return array(); $a = new dokuwiki_farm_animal($name); return array('success' => $a->setMetadata('status', $status)); } /** * Service that changes the lock state of an animal * @param $args SOAP arguments * @return success indicator */ function service_animalLockState($args) { $name = isset($args['name']) ? $args['name'] : ''; $lockstate = isset($args['lockstate']) ? $args['lockstate'] : ''; if($name == '' || in_array($lockstate, array('', 'none', 'edits', 'admin', 'all'))) return array(); if(!dokuwiki_farm_animal::exists($name)) return array(); $a = new dokuwiki_farm_animal($name); return array('success' => $a->setMetadata('lockstate', $lockstate)); } /** * Service that returns animals list * @param $args SOAP arguments * @return animal list */ function service_animalsList($args) { return array_map(create_function('$a', 'return array(\'name\' => $a->getName(), \'url\' => $a->getUrl());'), dokuwiki_farm_animal::listAnimals()); } } // Loads farm config and register SOAP handler, if no POST data then prints wsdl if(!defined('DOKU_CONF')) { define('DOKU_FARM_SOAPCONTEXT', true); ini_set('soap.wsdl_cache_enabled', '0'); if(!@file_exists('config.php')) die('No config found'); $farmconf = array(); include 'config.php'; if(!isset($farmconf['enablesoap'])) die(); if(!$farmconf['enablesoap']) die(); include 'animal.class.php'; $wsdl = $farmconf['farmfsroot'].'farm.wsdl'; $trace = 0; $soap_version = SOAP_1_1; if($_SERVER['REQUEST_METHOD'] == 'POST') { try { $server = new SoapServer($wsdl, array('trace' => $trace, 'soap_version' => $soap_version)); $server->setClass('farmSOAP', $server); $server->handle(); }catch(Exception $e) { die($e->getMessage()); } }else echo @file_get_contents($wsdl); }