1<?php 2/** 3 * Wiki farm SOAP server 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Etienne MELEARD <etienne.meleard@cru.fr> 7 * @desc Handle SOAP requests 8 */ 9 10/** 11 * Specific handler to gather errors 12 */ 13class SOAP_errorHandler { 14 var $errors = array(); 15 16 function __construct() {} 17 18 function getErrors() { 19 return array_values($this->errors); 20 } 21} 22 23/** 24 * Class that handles SOAP requests 25 */ 26class farmSOAP { 27 private $server = null; 28 29 /** 30 * @param $s reference to the SOAP handler 31 */ 32 function __construct($s) { 33 $this->server = $s; 34 } 35 36 /** 37 * Identify remote application and process SOAP requests 38 * @return array returned from service call 39 */ 40 function authenticateRemoteAppAndRun() { 41 $args = func_get_args(); 42 if(count($args) < 3) return array(); 43 44 // get call args 45 $appname = $args[0]; 46 $apppwd = $args[1]; 47 $service = $args[2]; 48 49 if($appname == '' || $apppwd == '' || $service == '') return array(); 50 51 $serviceargs = isset($args[3]) ? (is_array($args[3]) ? $args[3] : array($args[3])) : array(); 52 53 // identify app 54 $app = $this->getApp($appname); 55 if(!$app) return array(); 56 if(bin2hex(mhash(1, $apppwd)) != $app['pwd']) return array(); 57 58 // check rights 59 if(!isset($app['allowed'][$service])) return array(); 60 if(!method_exists($this, 'service_'.$service)) return array(); 61 62 // call and return 63 foreach($app['allowed'][$service] as $k => $v) { 64 if(is_array($v)) { 65 if(!in_array($serviceargs[$k], $v)) $serviceargs[$k] = reset($v); 66 }else $serviceargs[$k] = $v; 67 } 68 return call_user_func(array($this, 'service_'.$service), $serviceargs); 69 } 70 71 /** 72 * Check whether an application is in the trust list and gather its rights 73 * @param $name application name 74 * @return application descriptor 75 */ 76 function getApp($name) { 77 foreach(explode("\n\n", preg_replace('`<\?php[^?]+\?>\s*`i', '', file_get_contents('./trusted_apps.php'))) as $a) { 78 $app = array(); 79 foreach(explode("\n", trim($a)) as $f) { 80 if(preg_match('`^(name|pwd)\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) $app[$m[1]] = trim($m[2]); 81 if(preg_match('`^allowed\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) { 82 $app['allowed'] = array(); 83 $list = trim($m[1]); 84 while(preg_match('`^([^(,]+)(\(([^)]+)\))?(\s*,\s*(.*))?$`', $list, $m)) { 85 $sname = trim($m[1]); 86 $ovr = trim($m[3]); 87 $list = isset($m[5]) ? trim($m[5]) : ''; 88 89 $app['allowed'][$sname] = array(); 90 if($ovr != '') { 91 foreach(array_map('trim', explode(',', $ovr)) as $o) { 92 $o = array_map('trim', explode('=', $o)); 93 if(count($o) == 1) { 94 $app['allowed'][$sname][$o[0]] = true; 95 }elseif(count($o) == 2) { 96 if(preg_match('`^\[[^]]+\]$`', $o[1])) $o[1] = array_map('trim', explode(',', substr($o[1], 1, -1))); 97 elseif(preg_match('`^[0-9]+$`', $o[1])) $o[1] = (int)$o[1]; 98 elseif(preg_match('`^[0-9]+\.[0-9]+$`', $o[1])) $o[1] = (float)$o[1]; 99 elseif(preg_match('`^(true|false)$`i', $o[1])) $o[1] = (strtolower($o[1]) == 'true'); 100 elseif(preg_match('`^null$`i', $o[1])) $o[1] = null; 101 $app['allowed'][$sname][$o[0]] = $o[1]; 102 } 103 } 104 } 105 } 106 } 107 } 108 if(isset($app['name']) && $app['name'] == $name) return $app; 109 } 110 return null; 111 } 112 113 /* 114 *==========* 115 * SERVICES * 116 *==========* 117 */ 118 119 /** 120 * Simple service that returns args to check app auth & passed args 121 * @param $args SOAP arguments 122 * @return stuff 123 */ 124 function service_test($args) { 125 return array('appauth' => 'ok', 'args' => $args); 126 } 127 128 /** 129 * Service that creates an animal 130 * @param $args SOAP arguments 131 * @return success indicator and errors, also contains accepted name if successful (only different from original if it contained funky characters) 132 */ 133 function service_animalCreate($args) { 134 $name = isset($args['name']) ? $args['name'] : ''; 135 $template = isset($args['template']) ? $args['template'] : ''; 136 $host = isset($args['host']) ? $args['host'] : ''; // only used if farm is in virtual mode 137 $eh = new SOAP_errorHandler(); 138 if($n = dokuwiki_farm_animal::createNew($name, $template, $host, $eh)) { 139 return array('success' => true, 'name' => $n); 140 }else return array('success' => false, 'errors' => $eh->getErrors()); 141 } 142 143 /** 144 * Service that deletes an animal 145 * @param $args SOAP arguments 146 * @return success indicator 147 */ 148 function service_animalDelete($args) { 149 $name = isset($args['name']) ? $args['name'] : reset($args); 150 if(!dokuwiki_farm_animal::exists($name)) return array('success' => false); 151 $a = new dokuwiki_farm_animal($name); 152 return array('success' => $a->delete()); 153 } 154 155 /** 156 * Service that returns animal's status (existence/state) 157 * @param $args SOAP arguments 158 * @return animal status 159 */ 160 function service_animalExists($args) { 161 $name = isset($args['name']) ? $args['name'] : reset($args); 162 if(!dokuwiki_farm_animal::exists($args['name'])) return array('exists' => 0); 163 $a = new dokuwiki_farm_animal($args['name']); 164 return array( 165 'exists' => 1, 166 'status' => $a->getStatus(), 167 'locked' => $a->getLockState() 168 ); 169 } 170 171 /** 172 * Service that changes the status of an animal 173 * @param $args SOAP arguments 174 * @return success indicator 175 */ 176 function service_animalStatus($args) { 177 $name = isset($args['name']) ? $args['name'] : ''; 178 $status = isset($args['status']) ? $args['status'] : ''; 179 if($name == '' || in_array($status, array('open', 'maintenance', 'closed', 'abuse'))) return array(); 180 if(!dokuwiki_farm_animal::exists($name)) return array(); 181 $a = new dokuwiki_farm_animal($name); 182 return array('success' => $a->setMetadata('status', $status)); 183 } 184 185 /** 186 * Service that changes the lock state of an animal 187 * @param $args SOAP arguments 188 * @return success indicator 189 */ 190 function service_animalLockState($args) { 191 $name = isset($args['name']) ? $args['name'] : ''; 192 $lockstate = isset($args['lockstate']) ? $args['lockstate'] : ''; 193 if($name == '' || in_array($lockstate, array('', 'none', 'edits', 'admin', 'all'))) return array(); 194 if(!dokuwiki_farm_animal::exists($name)) return array(); 195 $a = new dokuwiki_farm_animal($name); 196 return array('success' => $a->setMetadata('lockstate', $lockstate)); 197 } 198 199 /** 200 * Service that returns animals list 201 * @param $args SOAP arguments 202 * @return animal list 203 */ 204 function service_animalsList($args) { 205 return array_map(create_function('$a', 'return array(\'name\' => $a->getName(), \'url\' => $a->getUrl());'), dokuwiki_farm_animal::listAnimals()); 206 } 207} 208 209// Loads farm config and register SOAP handler, if no POST data then prints wsdl 210if(!defined('DOKU_CONF')) { 211 define('DOKU_FARM_SOAPCONTEXT', true); 212 ini_set('soap.wsdl_cache_enabled', '0'); 213 214 if(!@file_exists('config.php')) die('No config found'); 215 216 $farmconf = array(); 217 include 'config.php'; 218 219 if(!isset($farmconf['enablesoap'])) die(); 220 if(!$farmconf['enablesoap']) die(); 221 222 include 'animal.class.php'; 223 224 $wsdl = $farmconf['farmfsroot'].'farm.wsdl'; 225 $trace = 0; 226 $soap_version = SOAP_1_1; 227 228 if($_SERVER['REQUEST_METHOD'] == 'POST') { 229 try { 230 $server = new SoapServer($wsdl, array('trace' => $trace, 'soap_version' => $soap_version)); 231 $server->setClass('farmSOAP', $server); 232 $server->handle(); 233 }catch(Exception $e) { 234 die($e->getMessage()); 235 } 236 }else echo @file_get_contents($wsdl); 237} 238