[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 // Copyright (c) 1999,2000,2001 Edd Dumbill. 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // 12 // * Redistributions in binary form must reproduce the above 13 // copyright notice, this list of conditions and the following 14 // disclaimer in the documentation and/or other materials provided 15 // with the distribution. 16 // 17 // * Neither the name of the "XML-RPC for PHP" nor the names of its 18 // contributors may be used to endorse or promote products derived 19 // from this software without specific prior written permission. 20 // 21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 32 // OF THE POSSIBILITY OF SUCH DAMAGE. 33 34 /* 35 * Incorporated for egroupware by Miles Lott <milos@groupwhere.org> 36 */ 37 38 /* $Id: class.xmlrpc_server_php.inc.php 20295 2006-02-15 12:31:25Z $ */ 39 40 /* BEGIN server class */ 41 class xmlrpc_server extends xmlrpc_server_shared 42 { 43 var $dmap = array(); 44 var $authed = False; 45 var $req_array = array(); 46 var $resp_struct = array(); 47 var $debug = False; 48 var $method_requested; 49 var $log = False; //'/tmp/xmlrpc.log'; 50 51 function xmlrpc_server($dispMap='', $serviceNow=0) 52 { 53 // dispMap is a dispatch array of methods 54 // mapped to function names and signatures 55 // if a method 56 // doesn't appear in the map then an unknown 57 // method error is generated 58 if($dispMap) 59 { 60 $this->dmap = $dispMap; 61 if ($serviceNow) 62 { 63 $this->service(); 64 } 65 } 66 } 67 68 function serializeDebug() 69 { 70 if ($GLOBALS['_xmlrpc_debuginfo'] != '') 71 { 72 return "<!-- DEBUG INFO:\n\n" . $GLOBALS['_xmlrpc_debuginfo'] . "\n-->\n"; 73 } 74 else 75 { 76 return ''; 77 } 78 } 79 80 function service($r=False) 81 { 82 if (!$r) // do we have a response, or we need to parse the request 83 { 84 $r = $this->parseRequest(); 85 } 86 if (!$r) 87 { 88 header('WWW-Authenticate: Basic realm="eGroupWare xmlrpc"'); 89 header('HTTP/1.0 401 Unauthorized'); 90 // for the log: 91 $payload = "WWW-Authenticate: Basic realm=\"eGroupWare xmlrpc\"\nHTTP/1.0 401 Unauthorized\n"; 92 } 93 else 94 { 95 $payload = "<?xml version=\"1.0\"?>\n" . $this->serializeDebug() . $r->serialize(); 96 header("Content-type: text/xml"); 97 header("Content-length: " . strlen($payload)); 98 echo $GLOBALS['egw']->translation->convert($payload,$GLOBALS['egw']->translation->charset(),'utf-8'); 99 } 100 101 if ($this->log) 102 { 103 $fp = fopen($this->log,'a+'); 104 fwrite($fp,"\n\n".date('Y-m-d H:i:s') . " authorized=" 105 . ($this->authed?$GLOBALS['egw_info']['user']['account_lid']:'False') 106 . ", method='$this->last_method'\n"); 107 fwrite($fp,"==== GOT ============================\n" . $GLOBALS['HTTP_RAW_POST_DATA'] 108 . "\n==== RETURNED =======================\n"); 109 fputs($fp,$payload); 110 fclose($fp); 111 } 112 113 if ($this->debug) 114 { 115 $this->echoInput(); 116 117 $fp = fopen('/tmp/xmlrpc_debug.out','w'); 118 fputs($fp,$payload); 119 fclose($fp); 120 } 121 } 122 123 /* 124 add a method to the dispatch map 125 */ 126 function add_to_map($methodname,$function,$sig,$doc) 127 { 128 $this->dmap[$methodname] = array( 129 'function' => $function, 130 'signature' => $sig, 131 'docstring' => $doc 132 ); 133 } 134 135 function verifySignature($in, $sig) 136 { 137 for($i=0; $i<sizeof($sig); $i++) 138 { 139 // check each possible signature in turn 140 $cursig = $sig[$i]; 141 if (sizeof($cursig) == $in->getNumParams()+1) 142 { 143 $itsOK = 1; 144 for($n=0; $n<$in->getNumParams(); $n++) 145 { 146 $p = $in->getParam($n); 147 // print "<!-- $p -->\n"; 148 if ($p->kindOf() == 'scalar') 149 { 150 $pt = $p->scalartyp(); 151 } 152 else 153 { 154 $pt = $p->kindOf(); 155 } 156 // $n+1 as first type of sig is return type 157 if ($pt != $cursig[$n+1]) 158 { 159 $itsOK = 0; 160 $pno = $n+1; 161 $wanted = $cursig[$n+1]; 162 $got = $pt; 163 break; 164 } 165 } 166 if ($itsOK) 167 { 168 return array(1); 169 } 170 } 171 } 172 return array(0, "Wanted $wanted, got $got at param $pno)"); 173 } 174 175 function reqtoarray($_req,$recursed=False) 176 { 177 switch(gettype($_req)) 178 { 179 case 'object': 180 if($recursed) 181 { 182 return $_req->getval(); 183 } 184 else 185 { 186 $this->req_array = $_req->getval(); 187 } 188 break; 189 case 'array': 190 @reset($_req); 191 $ele = array(); 192 while(list($key,$val) = @each($_req)) 193 { 194 if($recursed) 195 { 196 $ele[$key] = $this->reqtoarray($val,True); 197 } 198 else 199 { 200 $this->req_array[$key] = $this->reqtoarray($val,True); 201 } 202 } 203 if($recursed) 204 { 205 return $ele; 206 } 207 break; 208 case 'string': 209 case 'integer': 210 if($recursed) 211 { 212 return $_req; 213 } 214 else 215 { 216 $this->req_array[] = $_req; 217 } 218 break; 219 default: 220 break; 221 } 222 } 223 224 function build_resp($_res) 225 { 226 if (is_array($_res)) 227 { 228 $i = 0; 229 $is_array = True; 230 foreach($_res as $key => $val) 231 { 232 $ele[$key] = $this->build_resp($val,True); 233 $is_array = $is_array && $i === $key; 234 ++$i; 235 } 236 return CreateObject('phpgwapi.xmlrpcval',$ele,$is_array ? 'array' : 'struct'); 237 } 238 $_type = (is_integer($_res) ? 'int' : gettype($_res)); 239 240 if ($_type == 'string' && (ereg('^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$',$_res) || 241 ereg('^[0-9]{4}[0-9]{2}[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}$',$_res))) 242 { 243 $_type = 'dateTime.iso8601'; 244 } 245 // Passing an integer of 0 to the xmlrpcval constructor results in the value being lost. (jengo) 246 if ($_type == 'int' && $_res == 0) 247 { 248 return CreateObject('phpgwapi.xmlrpcval','0',$_type); 249 } 250 return CreateObject('phpgwapi.xmlrpcval',$_res,$_type); 251 } 252 253 function parseRequest($data='') 254 { 255 $r = False; 256 257 if ($data == '') 258 { 259 $data = $GLOBALS['HTTP_RAW_POST_DATA']; 260 } 261 $parser = xml_parser_create($GLOBALS['xmlrpc_defencoding']); 262 263 $GLOBALS['_xh'][$parser] = array(); 264 $GLOBALS['_xh'][$parser]['isf'] = 0; 265 $GLOBALS['_xh'][$parser]['isf_reason'] = ''; 266 $GLOBALS['_xh'][$parser]['params'] = array(); 267 $GLOBALS['_xh'][$parser]['stack']=array(); 268 $GLOBALS['_xh'][$parser]['valuestack'] = array(); 269 $GLOBALS['_xh'][$parser]['method'] = ''; 270 271 // decompose incoming XML into request structure 272 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); 273 xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); 274 xml_set_character_data_handler($parser, 'xmlrpc_cd'); 275 xml_set_default_handler($parser, 'xmlrpc_dh'); 276 if (!xml_parse($parser, $data, 1)) 277 { 278 // return XML error as a faultCode 279 $r = CreateObject('phpgwapi.xmlrpcresp','', 280 $GLOBALS['xmlrpcerrxml'] + xml_get_error_code($parser), 281 sprintf('XML error: %s at line %d', 282 xml_error_string(xml_get_error_code($parser)), 283 xml_get_current_line_number($parser)) 284 ); 285 xml_parser_free($parser); 286 } 287 elseif ($GLOBALS['_xh'][$parser]['isf']) 288 { 289 xml_parser_free($parser); 290 $r = CreateObject( 291 'phpgwapi.xmlrpcresp', 292 0, 293 $GLOBALS['xmlrpcerr']['invalid_request'], 294 $GLOBALS['xmlrpcstr']['invalid_request'] . ' ' . $GLOBALS['_xh'][$parser]['isf_reason'] 295 ); 296 } 297 else 298 { 299 xml_parser_free($parser); 300 $m = CreateObject('phpgwapi.xmlrpcmsg',$GLOBALS['_xh'][$parser]['method']); 301 // now add parameters in 302 $plist = ''; 303 for($i=0; $i<sizeof($GLOBALS['_xh'][$parser]['params']); $i++) 304 { 305 // print "<!-- " . $GLOBALS['_xh'][$parser]['params'][$i]. "-->\n"); 306 $m->addParam($GLOBALS['_xh'][$parser]['params'][$i]); 307 } 308 309 // now to deal with the method 310 $methName = $GLOBALS['_xh'][$parser]['method']; 311 $_methName = $GLOBALS['_xh'][$parser]['method']; 312 $this->last_method = $methName; 313 314 if(ereg("^system\.", $methName)) 315 { 316 $dmap = $GLOBALS['_xmlrpcs_dmap']; 317 $sysCall=1; 318 } 319 else 320 { 321 $dmap = $this->dmap; 322 $sysCall=0; 323 } 324 325 if(!isset($dmap[$methName]['function'])) 326 { 327 if($sysCall && $this->authed) 328 { 329 $r = CreateObject('phpgwapi.xmlrpcresp', 330 '', 331 $GLOBALS['xmlrpcerr']['unknown_method'], 332 $GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName 333 ); 334 return $r; 335 } 336 if($this->authed) 337 { 338 /* phpgw mod - fetch the (bo) class methods to create the dmap */ 339 // This part is to update session action to match 340 $this->method_requested = $methName; 341 342 $method = $methName; 343 $tmp = explode('.',$methName); 344 $methName = $tmp[2]; 345 $service = $tmp[1]; 346 $class = $tmp[0]; 347 348 if(ereg('^service',$method)) 349 { 350 $t = 'phpgwapi.' . $class . '.exec'; 351 $dmap = ExecMethod($t,array($service,'list_methods','xmlrpc')); 352 } 353 elseif($GLOBALS['egw']->acl->check('run',1,$class)) 354 { 355 /* This only happens if they have app access. If not, we will 356 * return a fault below. 357 */ 358 $listmeth = $class . '.' . $service . '.' . 'list_methods'; 359 $dmap = ExecMethod($listmeth,'xmlrpc'); 360 } 361 else 362 { 363 $r = CreateObject('phpgwapi.xmlrpcresp', 364 '', 365 $GLOBALS['xmlrpcerr']['no_access'], 366 $GLOBALS['xmlrpcstr']['no_access'] 367 ); 368 return $r; 369 } 370 371 $this->dmap = $dmap; 372 /* _debug_array($this->dmap);exit; */ 373 } 374 } 375 376 if (isset($dmap[$methName]['function'])) 377 { 378 // dispatch if exists 379 if (isset($dmap[$methName]['signature'])) 380 { 381 list($sr, $errstr) = $this->verifySignature($m, $dmap[$methName]['signature']); 382 if(!$sr) 383 { 384 // Didn't match. 385 386 return CreateObject( 387 'phpgwapi.xmlrpcresp', 388 0, 389 $GLOBALS['xmlrpcerr']['incorrect_params'], 390 $GLOBALS['xmlrpcstr']['incorrect_params'] . ": $errstr}" 391 ); 392 } 393 } 394 if((!isset($dmap[$methName]['signature'])) || $sr) 395 { 396 // if no signature or correct signature 397 if($sysCall) 398 { 399 $r = call_user_func($dmap[$methName]['function'], $this, $m); 400 } 401 else 402 { 403 if(function_exists($dmap[$methName]['function'])) 404 { 405 $r = call_user_func($dmap[$methName]['function'],$m); 406 } 407 else 408 { 409 /* phpgw mod - finally, execute the function call and return the values */ 410 $params = $GLOBALS['_xh'][$parser]['params'][0]; 411 if(count($params) != 0) 412 { 413 $p = $params; 414 $params = $p->getval(); 415 } 416 417 // _debug_array($params); 418 $this->reqtoarray($params); 419 // decode from utf-8 to our charset 420 $this->req_array = $GLOBALS['egw']->translation->convert($this->req_array,'utf-8'); 421 //_debug_array($this->req_array); 422 if (ereg('^service',$method)) 423 { 424 $res = ExecMethod('phpgwapi.service.exec',array($service,$methName,$this->req_array)); 425 } 426 else 427 { 428 list($s,$c,$m) = explode('.',$_methName); 429 $res = ExecMethod($s . '.' . $c . '.' . $dmap[$methName]['function'],$this->req_array); 430 } 431 //$this->resp_struct = array($this->build_resp($res,True)); 432 //@reset($this->resp_struct); 433 //$r = CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$this->resp_struct,'struct')); 434 // this fixes the unnecessary (and not standard-conform) array/xmlrpc struct around everything 435 $r = CreateObject('phpgwapi.xmlrpcresp',$this->build_resp($res,True)); 436 // _debug_array($r); 437 } 438 } 439 } 440 else 441 { 442 $r = CreateObject('phpgwapi.xmlrpcresp', 443 '', 444 $GLOBALS['xmlrpcerr']['incorrect_params'], 445 $GLOBALS['xmlrpcstr']['incorrect_params'] . ': ' . $sr[1] 446 ); 447 } 448 } 449 else 450 { 451 // else prepare error response 452 if(!$this->authed) 453 { 454 $r = False; // send 401 header to force authorization 455 /*CreateObject('phpgwapi.xmlrpcresp', 456 CreateObject('phpgwapi.xmlrpcval', 457 'UNAUTHORIZED', 458 'string' 459 ) 460 );*/ 461 } 462 else 463 { 464 $r = CreateObject('phpgwapi.xmlrpcresp', 465 '', 466 $GLOBALS['xmlrpcerr']['unknown_method'], 467 $GLOBALS['xmlrpcstr']['unknown_method'] . ': ' . $methName 468 ); 469 } 470 } 471 } 472 unset($GLOBALS['_xh'][$parser]); 473 return $r; 474 } 475 476 function echoInput() 477 { 478 // a debugging routine: just echos back the input 479 // packet as a string value 480 481 $r = CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',"'Aha said I: '" 482 . $GLOBALS['HTTP_RAW_POST_DATA'],'string')); 483 //echo $r->serialize(); 484 485 $fp = fopen('/tmp/xmlrpc_debug.in','w'); 486 fputs($fp,$r->serialize); 487 fputs($fp,$GLOBALS['HTTP_RAW_POST_DATA']); 488 fclose($fp); 489 } 490 491 function xmlrpc_error($error_number, $error_string) 492 { 493 $r = CreateObject('phpgwapi.xmlrpcresp', 494 '', 495 $error_number, 496 $error_string . ': ' . $this->last_method 497 ); 498 $this->service($r); 499 exit; 500 } 501 } 502 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |