1<?php 2/** 3 * Wiki farm manager 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Etienne MELEARD <etienne.meleard@cru.fr> 7 * @desc Process and renders SOAP server config related requests 8 */ 9 10// must be run within Dokuwiki 11if(!defined('DOKU_INC')) die(); 12 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); 14if(!defined('DOKU_FARM_PLUGIN')) define('DOKU_FARM_PLUGIN', DOKU_PLUGIN.'farm/'); 15 16if(!defined('DOKU_FARMPLUGINLOADED')) define('DOKU_FARMPLUGINLOADED', true); 17 18class dokuwiki_farm_soapconfig { 19 var $data = array(); 20 var $manager = null; 21 var $errors = array(); 22 23 /** 24 * @param $manager object that must handle error(), success(), nicesize(), getLang() ... calls 25 */ 26 function __construct($manager) { 27 $this->manager = & $manager; 28 } 29 30 /** 31 * Builds a link inside SOAP config tab 32 * @param $opts farm option array 33 * @return url string 34 */ 35 function wl($opts = array()) { 36 return $this->manager->wl('soapconfig', $opts); 37 } 38 39 /** 40 * Process requests 41 */ 42 function process() { 43 // Parameters check 44 if( 45 !(isset($this->manager->opt['app']) && isset($this->manager->opt['save'])) && 46 !(isset($this->manager->opt['app']) && isset($this->manager->opt['delete'])) && 47 !(isset($this->manager->opt['new']) && isset($this->manager->opt['save'])) && 48 !isset($this->manager->opt['advancedsave']) 49 ) return; 50 51 // Security check 52 if(!checkSecurityToken()) { 53 $this->manager->error('system_errors', 'system_badtoken_failure'); 54 return; // any changes done by post 55 } 56 57 // Text mode save request 58 if(isset($this->manager->opt['advancedsave'])) { 59 if(!isset($_POST['soap_config_advanced']) || empty($_POST['soap_config_advanced'])) { 60 $this->manager->error('system_errors', 'postparametermissing_failure'); 61 return; 62 } 63 if($fp = fopen(DOKU_FARM_PLUGIN.'trusted_apps.php', 'w')) { 64 fwrite($fp, '<?php exit(); ?>'."\n".$_POST['soap_config_advanced']); 65 fclose($fp); 66 }else $this->manager->error('soapconfig_errors', 'soapconfig_save_failure'); 67 return; 68 } 69 70 // Trusted application deletion request 71 if(isset($this->manager->opt['delete']) && isset($this->manager->opt['app'])) { 72 $out = array(); 73 foreach(explode("\n\n", @file_get_contents(DOKU_FARM_PLUGIN.'trusted_apps.php')) as $p) { 74 $appname = ''; 75 foreach(explode("\n", trim($p)) as $f) if(preg_match('`^name\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) $appname = trim($m[1]); 76 if($appname != $this->manager->opt['app']) $out[] = $p; 77 } 78 if($fp = fopen(DOKU_FARM_PLUGIN.'trusted_apps.php', 'w')) { 79 fwrite($fp, $out); 80 fclose($fp); 81 unset($this->manager->opt['app']); 82 $this->manager->success('soapconfig_save_success'); 83 }else $this->manager->error('soapconfig_errors', 'soapconfig_save_failure'); 84 return; 85 } 86 87 // Parameters check 88 if( 89 !isset($_POST['soap_remoteapp_name']) || empty($_POST['soap_remoteapp_name']) || !preg_match('`^[a-z0-9_-]+$`i', $_POST['soap_remoteapp_name']) || 90 !isset($_POST['soap_remoteapp_namecomment']) || 91 !isset($_POST['soap_remoteapp_pwd']) || 92 !isset($_POST['soap_remoteapp_pwdcomment']) || 93 !isset($_POST['soap_remoteapp_serviceallowed']) || 94 !isset($_POST['soap_remoteapp_serviceimposedargs']) || 95 !isset($_POST['soap_remoteapp_servicescomment']) 96 ) { 97 $this->manager->error('system_errors', 'postparametermissing_failure'); 98 return; 99 } 100 101 // Basic mode save / add 102 103 $name = $_POST['soap_remoteapp_name']; 104 $namecomment = str_replace(array("\n", "\r"), '', $_POST['soap_remoteapp_namecomment']); 105 106 $pwdh = function_exists('md5') ? md5($_POST['soap_remoteapp_pwd']) : (function_exists('mhash') ? bin2hex(mhash(1, $_POST['soap_remoteapp_pwd'])) : null); 107 $pwd = preg_match('`^[0-9abcdef]{32}$`i', $_POST['soap_remoteapp_pwd']) ? strtolower($_POST['soap_remoteapp_pwd']) : $pwdh; 108 $pwdclear = str_replace(array("\n", "\r"), '', $_POST['soap_remoteapp_pwd']); 109 $pwdcomment = str_replace(array("\n", "\r"), '', $_POST['soap_remoteapp_pwdcomment']); 110 111 $allowedcomment = str_replace(array("\n", "\r"), '', $_POST['soap_remoteapp_serviceallowedcomment']); 112 113 $block = '# '.$name.' app'."\n"; 114 $block .= 'name = '.$name.($namecomment != '' ? ' # '.$namecomment : '')."\n"; 115 $block .= 'pwd = '.$pwd.' '.(($pwdclear != $pwd) || ($pwdcomment != '') ? '# '.($pwd != $pwdclear ? '('.$pwdclear.') ' : '').$pwdcomment : '')."\n"; 116 $allowed = array(); 117 include 'soapserver.php'; 118 foreach(get_class_methods('farmSOAP') as $m) { 119 if(strpos($m, 'service_') !== 0) continue; 120 $m = substr($m, 8); 121 if(isset($_POST['soap_remoteapp_serviceallowed'][$m])) $allowed[] = $m.((isset($_POST['soap_remoteapp_serviceimposedargs'][$m]) && !empty($_POST['soap_remoteapp_serviceimposedargs'][$m])) ? '('.$_POST['soap_remoteapp_serviceimposedargs'][$m].')' : ''); 122 } 123 $block .= 'allowed = '.implode(', ', $allowed).($allowedcomment != '' ? ' # '.$allowedcomment : ''); 124 125 if(isset($this->manager->opt['new']) && isset($this->manager->opt['save'])) { 126 $app = ''; 127 $file = @file_get_contents(DOKU_FARM_PLUGIN.'trusted_apps.php'); 128 if(!$file) { 129 $this->manager->error('soapconfig_errors', 'soapconfig_corruptedfile_failure'); 130 return; 131 } 132 133 if($fp = fopen(DOKU_FARM_PLUGIN.'trusted_apps.php', 'w')) { 134 fwrite($fp, $file."\n\n".$block); 135 fclose($fp); 136 $this->manager->opt['app'] = $name; 137 $this->manager->success('soapconfig_save_success'); 138 return; 139 }else $this->manager->error('soapconfig_errors', 'soapconfig_save_failure'); 140 141 } 142 143 if(isset($this->manager->opt['save']) && isset($this->manager->opt['app'])) { 144 $out = array(); 145 foreach(explode("\n\n", @file_get_contents(DOKU_FARM_PLUGIN.'trusted_apps.php')) as $p) { 146 $appname = ''; 147 foreach(explode("\n", trim($p)) as $f) if(preg_match('`^name\s*=\s*([^#]+)(#.*)?$`i', trim($f), $m)) $appname = trim($m[1]); 148 if($appname != $this->manager->opt['app']) { 149 $out[] = $p; 150 }else $out[] = $block; 151 } 152 if($fp = fopen(DOKU_FARM_PLUGIN.'trusted_apps.php', 'w')) { 153 fwrite($fp, implode("\n\n", $out)); 154 fclose($fp); 155 $this->manager->opt['app'] = $name; 156 $this->manager->success('soapconfig_save_success'); 157 }else $this->manager->error('soapconfig_errors', 'soapconfig_save_failure'); 158 return; 159 } 160 } 161 162 /** 163 * Renders 164 */ 165 function html() { 166 global $ID; 167 ptln('<div class="farm_cmd_title">'.$this->manager->getLang('soapconfig_title').'</div>'); 168 ptln('<div class="farm_cmd_info">'.$this->manager->getLang('soapconfig_info').'</div>'); 169 ptln($this->manager->getLang('soapconfig_wsdlurl', array($this->manager->conf['farmwebroot'].'farm.wsdl'))); 170 ptln('<div class="soapapp soapapp_new">'); 171 ptln(' <a href="'.$this->wl(array('new' => 1)).'" title="'.$this->manager->getLang('soapconfig_newapp').'"><img src="'.DOKU_FARM_WWW.'images/add.png" alt="add remote app" /> '.$this->manager->getLang('soapconfig_newapp').'</a>'); 172 ptln(' <a href="'.$this->wl(array('advanced' => 1)).'" title="'.$this->manager->getLang('soapconfig_advancededit').'"><img src="'.DOKU_FARM_WWW.'images/txt.png" alt="advanced edit mode" /> '.$this->manager->getLang('soapconfig_advancededit').'</a>'); 173 ptln('</div>'); 174 175 if(isset($this->manager->opt['advanced'])) { 176 $this->manager->formHead(array('farm_cmd' => 'soapconfig')); 177 ptln('<fieldset>'); 178 ptln(' <textarea rows="20" style="width:100%;overflow:auto;" name="soap_config_advanced">'.preg_replace('`<\?php\s*exit\(\);\s*\?>`', '', @file_get_contents(DOKU_FARM_PLUGIN.'trusted_apps.php')).'</textarea>'); 179 ptln('</fieldset>'); 180 ptln(' <fieldset class="save">'); 181 ptln(' <input type="submit" class="button" name="farm_opt[advancedsave]" value="'.$this->manager->getLang('btn_save').'" />'); 182 ptln(' </fieldset>'); 183 ptln('</form>'); 184 }else{ 185 $apps = $this->getApps(); 186 foreach($apps as $a) { 187 ptln('<div class="soapapp">'); 188 ptln(' '.$this->manager->getLang('soapconfig_field_name_name').' : '.$a['name']['value'].' '.($a['name']['comment'] != '' ? ' <i>('.$this->manager->getLang('soapconfig_comment').' : '.$a['name']['comment'].')</i>' : '').'<br />'); 189 ptln(' '.$this->manager->getLang('soapconfig_field_name_passwordhash').' : '.$a['pwd']['value'].($a['pwd']['comment'] != '' ? ' <i>('.$this->manager->getLang('soapconfig_comment').' : '.$a['pwd']['comment'].')</i>' : '').'<br />'); 190 ptln(' '.$this->manager->getLang('soapconfig_field_name_allowedservices').' : '.implode(', ', array_keys($a['allowed']['value'])).''.($a['allowed']['comment'] != '' ? ' <i>('.$this->manager->getLang('soapconfig_comment').' : '.$a['allowed']['comment'].')</i>' : '').'<br />'); 191 ptln(' <a href="'.$this->wl(array('app' => $a['name']['value'])).'#remoteapp_edit" title="'.$this->manager->getLang('soapconfig_editapp').'"><img src="'.DOKU_FARM_WWW.'images/edit.png" alt="edit remote app" /></a>'); 192 ptln('</div>'); 193 } 194 195 if(isset($this->manager->opt['app']) || isset($this->manager->opt['new'])) { 196 ptln('<div class="soapedit">'.$this->manager->getLang('soapconfig_'.(isset($this->manager->opt['app']) ? 'edit' : 'new').'app').'</div>'); 197 $hf = array('farm_cmd' => 'soapconfig'); 198 if(isset($this->manager->opt['app'])) $hf['farm_opt[app]'] = $this->manager->opt['app']; 199 else $hf['farm_opt[new]'] = 1; 200 $a = isset($this->manager->opt['app']) ? $apps[$this->manager->opt['app']] : null; 201 ptln('<a name="remoteapp_edit"></a>'); 202 $this->manager->formHead($hf); 203 ptln('<fieldset>'); 204 ptln(' '.$this->manager->getLang('soapconfig_field_name_name').' : <input type="text" name="soap_remoteapp_name" value="'.($a ? $a['name']['value'] : '').'" /><br />'); 205 ptln(' '.$this->manager->getLang('soapconfig_comment').' : <input type="text" name="soap_remoteapp_namecomment" value="'.($a ? $a['name']['comment'] : '').'" /><br />'); 206 ptln(' <small>'.$this->manager->getLang('soapconfig_field_desc_name').'</small>'); 207 ptln('</fieldset>'); 208 209 ptln('<fieldset>'); 210 ptln(' '.$this->manager->getLang('soapconfig_field_name_passwordhash').' : <input type="text" name="soap_remoteapp_pwd" value="'.($a ? $a['pwd']['value'] : '').'" /><br />'); 211 ptln(' '.$this->manager->getLang('soapconfig_comment').' : <input type="text" name="soap_remoteapp_pwdcomment" value="'.($a ? $a['pwd']['comment'] : '').'" /><br />'); 212 ptln(' <small>'.$this->manager->getLang('soapconfig_field_desc_passwordhash').'</small><br />'); 213 if(function_exists('md5') || function_exists('mhash')) { 214 ptln(' '.$this->manager->getLang('soapconfig_field_name_passwordhash_change')); 215 }else{ 216 ptln(' '.$this->manager->getLang('soapconfig_field_name_passwordhash_change_nohashfunc')); 217 } 218 ptln('</fieldset>'); 219 220 ptln('<fieldset>'); 221 ptln(' '.$this->manager->getLang('soapconfig_field_name_allowedservices').' : <br />'); 222 ptln(' <small>'.$this->manager->getLang('soapconfig_field_desc_allowedservice_imposedargs').'</small><br />'); 223 if(!class_exists('farmSOAP')) include 'soapserver.php'; 224 foreach(get_class_methods('farmSOAP') as $m) { 225 if(strpos($m, 'service_') !== 0) continue; 226 $m = substr($m, 8); 227 ptln(' <div class="soapapp_service">'); 228 ptln(' <input type="checkbox" name="soap_remoteapp_serviceallowed['.$m.']" '.($a ? (isset($a['allowed']['value'][$m]) ? 'checked="checked"' : '') : '').' /> '.$m.' :<br />'); 229 ptln(' <small>'.$this->manager->getLang('soapconfig_field_desc_allowedservice_'.$m).'</small><br />'); 230 $imp = ''; 231 if($a) { 232 if(isset($a['allowed']['value'][$m])) { 233 $imp = $a['allowed']['value'][$m]; 234 foreach($imp as $k => $v) $imp[$k] = $k.'='.$v; 235 $imp = implode(', ', $imp); 236 } 237 } 238 ptln(' '.$this->manager->getLang('soapconfig_field_name_allowedservice_imposedargs').' : <input type="text" name="soap_remoteapp_serviceimposedargs['.$m.']" value="'.$imp.'" /><br />'); 239 ptln(' </div>'); 240 } 241 ptln(' '.$this->manager->getLang('soapconfig_comment').' : <input type="text" name="soap_remoteapp_servicescomment" value="'.($a ? $a['allowed']['comment'] : '').'" /><br />'); 242 ptln(' <small>'.$this->manager->getLang('soapconfig_field_desc_allowedservices').'</small>'); 243 ptln('</fieldset>'); 244 245 ptln(' <fieldset class="save">'); 246 ptln(' <input type="submit" class="button" name="farm_opt[save]" value="'.$this->manager->getLang('btn_save').'" />'); 247 if($a) ptln(' <input type="button" class="button" onclick="if(this.type==\'submit\')return true;if(confirm(\''.$this->manager->getLang('soapconfig_appdelete_sure', $a['name']['value'], 'js').'\')){this.type=\'submit\';this.click();}" name="farm_opt[delete]" value="'.$this->manager->getLang('btn_delete').'" />'); 248 ptln(' </fieldset>'); 249 ptln('</form>'); 250 } 251 } 252 } 253 254 /** 255 * Returns the list of trusted applications 256 * @return array of application descriptors 257 */ 258 function getApps() { 259 $apps = array(); 260 foreach(explode("\n\n", preg_replace('`<\?php[^?]+\?>\s*`i', '', @file_get_contents(DOKU_FARM_PLUGIN.'trusted_apps.php'))) as $a) { 261 $app = array(); 262 foreach(explode("\n", trim($a)) as $f) { 263 if(preg_match('`^(name|pwd)\s*=\s*([^#]+)(#(.*))?$`i', trim($f), $m)) { 264 $app[strtolower($m[1])] = array( 265 'value' => trim($m[2]), 266 'comment' => isset($m[4]) ? trim($m[4]) : '' 267 ); 268 } 269 if(preg_match('`^allowed\s*=\s*([^#]+)(#(.*))?$`i', trim($f), $m)) { 270 $list = trim($m[1]); 271 $app['allowed'] = array( 272 'value' => array(), 273 'comment' => isset($m[3]) ? trim($m[3]) : '' 274 ); 275 while(preg_match('`^([^(,]+)(\(([^)]+)\))?(\s*,\s*(.*))?$`', $list, $m)) { 276 $sname = trim($m[1]); 277 $ovr = trim($m[3]); 278 $list = isset($m[5]) ? trim($m[5]) : ''; 279 280 $app['allowed']['value'][$sname] = array(); 281 if($ovr != '') { 282 foreach(array_map('trim', explode(',', $ovr)) as $o) { 283 $o = array_map('trim', explode('=', $o)); 284 if(count($o) == 1) { 285 $app['allowed']['value'][$sname][$o[0]] = true; 286 }elseif(count($o) == 2) { 287 if(preg_match('`^\[[^]]+\]$`', $o[1])) $o[1] = array_map('trim', explode(',', substr($o[1], 1, -1))); 288 elseif(preg_match('`^[0-9]+$`', $o[1])) $o[1] = (int)$o[1]; 289 elseif(preg_match('`^[0-9]+\.[0-9]+$`', $o[1])) $o[1] = (float)$o[1]; 290 elseif(preg_match('`^(true|false)$`i', $o[1])) $o[1] = (strtolower($o[1]) == 'true'); 291 elseif(preg_match('`^null$`i', $o[1])) $o[1] = null; 292 $app['allowed']['value'][$sname][$o[0]] = $o[1]; 293 } 294 } 295 } 296 } 297 } 298 } 299 if(isset($app['name']['value']) && $app['name']['value'] != '') $apps[$app['name']['value']] = $app; 300 } 301 return $apps; 302 } 303} 304?> 305