| [ Index ] |
|
Code source de Serendipity 1.2 |
1 <?php 2 3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ 4 5 /** 6 * Server commands for our PHP implementation of the XML-RPC protocol 7 * 8 * This is a PEAR-ified version of Useful inc's XML-RPC for PHP. 9 * It has support for HTTP transport, proxies and authentication. 10 * 11 * PHP versions 4 and 5 12 * 13 * LICENSE: License is granted to use or modify this software 14 * ("XML-RPC for PHP") for commercial or non-commercial use provided the 15 * copyright of the author is preserved in any distributed or derivative work. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESSED OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * @category Web Services 29 * @package XML_RPC 30 * @author Edd Dumbill <edd@usefulinc.com> 31 * @author Stig Bakken <stig@php.net> 32 * @author Martin Jansen <mj@php.net> 33 * @author Daniel Convissor <danielc@php.net> 34 * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group 35 * @version CVS: $Id: Server.php,v 1.29 2005/08/14 20:25:35 danielc Exp $ 36 * @link http://pear.php.net/package/XML_RPC 37 */ 38 39 40 /** 41 * Pull in the XML_RPC class 42 */ 43 require_once dirname(__FILE__) . '/../RPC.php'; 44 45 /** 46 * signature for system.listMethods: return = array, 47 * parameters = a string or nothing 48 * @global array $GLOBALS['XML_RPC_Server_listMethods_sig'] 49 */ 50 $GLOBALS['XML_RPC_Server_listMethods_sig'] = array( 51 array($GLOBALS['XML_RPC_Array'], 52 $GLOBALS['XML_RPC_String'] 53 ), 54 array($GLOBALS['XML_RPC_Array']) 55 ); 56 57 /** 58 * docstring for system.listMethods 59 * @global string $GLOBALS['XML_RPC_Server_listMethods_doc'] 60 */ 61 $GLOBALS['XML_RPC_Server_listMethods_doc'] = 'This method lists all the' 62 . ' methods that the XML-RPC server knows how to dispatch'; 63 64 /** 65 * signature for system.methodSignature: return = array, 66 * parameters = string 67 * @global array $GLOBALS['XML_RPC_Server_methodSignature_sig'] 68 */ 69 $GLOBALS['XML_RPC_Server_methodSignature_sig'] = array( 70 array($GLOBALS['XML_RPC_Array'], 71 $GLOBALS['XML_RPC_String'] 72 ) 73 ); 74 75 /** 76 * docstring for system.methodSignature 77 * @global string $GLOBALS['XML_RPC_Server_methodSignature_doc'] 78 */ 79 $GLOBALS['XML_RPC_Server_methodSignature_doc'] = 'Returns an array of known' 80 . ' signatures (an array of arrays) for the method name passed. If' 81 . ' no signatures are known, returns a none-array (test for type !=' 82 . ' array to detect missing signature)'; 83 84 /** 85 * signature for system.methodHelp: return = string, 86 * parameters = string 87 * @global array $GLOBALS['XML_RPC_Server_methodHelp_sig'] 88 */ 89 $GLOBALS['XML_RPC_Server_methodHelp_sig'] = array( 90 array($GLOBALS['XML_RPC_String'], 91 $GLOBALS['XML_RPC_String'] 92 ) 93 ); 94 95 /** 96 * docstring for methodHelp 97 * @global string $GLOBALS['XML_RPC_Server_methodHelp_doc'] 98 */ 99 $GLOBALS['XML_RPC_Server_methodHelp_doc'] = 'Returns help text if defined' 100 . ' for the method passed, otherwise returns an empty string'; 101 102 /** 103 * dispatch map for the automatically declared XML-RPC methods. 104 * @global array $GLOBALS['XML_RPC_Server_dmap'] 105 */ 106 $GLOBALS['XML_RPC_Server_dmap'] = array( 107 'system.listMethods' => array( 108 'function' => 'XML_RPC_Server_listMethods', 109 'signature' => $GLOBALS['XML_RPC_Server_listMethods_sig'], 110 'docstring' => $GLOBALS['XML_RPC_Server_listMethods_doc'] 111 ), 112 'system.methodHelp' => array( 113 'function' => 'XML_RPC_Server_methodHelp', 114 'signature' => $GLOBALS['XML_RPC_Server_methodHelp_sig'], 115 'docstring' => $GLOBALS['XML_RPC_Server_methodHelp_doc'] 116 ), 117 'system.methodSignature' => array( 118 'function' => 'XML_RPC_Server_methodSignature', 119 'signature' => $GLOBALS['XML_RPC_Server_methodSignature_sig'], 120 'docstring' => $GLOBALS['XML_RPC_Server_methodSignature_doc'] 121 ) 122 ); 123 124 /** 125 * @global string $GLOBALS['XML_RPC_Server_debuginfo'] 126 */ 127 $GLOBALS['XML_RPC_Server_debuginfo'] = ''; 128 129 130 /** 131 * Lists all the methods that the XML-RPC server knows how to dispatch 132 * 133 * @return object a new XML_RPC_Response object 134 */ 135 function XML_RPC_Server_listMethods($server, $m) 136 { 137 global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; 138 139 $v = new XML_RPC_Value(); 140 $outAr = array(); 141 foreach ($server->dmap as $key => $val) { 142 $outAr[] = new XML_RPC_Value($key, 'string'); 143 } 144 foreach ($XML_RPC_Server_dmap as $key => $val) { 145 $outAr[] = new XML_RPC_Value($key, 'string'); 146 } 147 $v->addArray($outAr); 148 return new XML_RPC_Response($v); 149 } 150 151 /** 152 * Returns an array of known signatures (an array of arrays) 153 * for the given method 154 * 155 * If no signatures are known, returns a none-array 156 * (test for type != array to detect missing signature) 157 * 158 * @return object a new XML_RPC_Response object 159 */ 160 function XML_RPC_Server_methodSignature($server, $m) 161 { 162 global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; 163 164 $methName = $m->getParam(0); 165 $methName = $methName->scalarval(); 166 if (strpos($methName, 'system.') === 0) { 167 $dmap = $XML_RPC_Server_dmap; 168 $sysCall = 1; 169 } else { 170 $dmap = $server->dmap; 171 $sysCall = 0; 172 } 173 // print "<!-- ${methName} -->\n"; 174 if (isset($dmap[$methName])) { 175 if ($dmap[$methName]['signature']) { 176 $sigs = array(); 177 $thesigs = $dmap[$methName]['signature']; 178 for ($i = 0; $i < sizeof($thesigs); $i++) { 179 $cursig = array(); 180 $inSig = $thesigs[$i]; 181 for ($j = 0; $j < sizeof($inSig); $j++) { 182 $cursig[] = new XML_RPC_Value($inSig[$j], 'string'); 183 } 184 $sigs[] = new XML_RPC_Value($cursig, 'array'); 185 } 186 $r = new XML_RPC_Response(new XML_RPC_Value($sigs, 'array')); 187 } else { 188 $r = new XML_RPC_Response(new XML_RPC_Value('undef', 'string')); 189 } 190 } else { 191 $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], 192 $XML_RPC_str['introspect_unknown']); 193 } 194 return $r; 195 } 196 197 /** 198 * Returns help text if defined for the method passed, otherwise returns 199 * an empty string 200 * 201 * @return object a new XML_RPC_Response object 202 */ 203 function XML_RPC_Server_methodHelp($server, $m) 204 { 205 global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; 206 207 $methName = $m->getParam(0); 208 $methName = $methName->scalarval(); 209 if (strpos($methName, 'system.') === 0) { 210 $dmap = $XML_RPC_Server_dmap; 211 $sysCall = 1; 212 } else { 213 $dmap = $server->dmap; 214 $sysCall = 0; 215 } 216 217 if (isset($dmap[$methName])) { 218 if ($dmap[$methName]['docstring']) { 219 $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]['docstring']), 220 'string'); 221 } else { 222 $r = new XML_RPC_Response(new XML_RPC_Value('', 'string')); 223 } 224 } else { 225 $r = new XML_RPC_Response(0, $XML_RPC_err['introspect_unknown'], 226 $XML_RPC_str['introspect_unknown']); 227 } 228 return $r; 229 } 230 231 /** 232 * @return void 233 */ 234 function XML_RPC_Server_debugmsg($m) 235 { 236 global $XML_RPC_Server_debuginfo; 237 $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; 238 } 239 240 241 /** 242 * A server for receiving and replying to XML RPC requests 243 * 244 * <code> 245 * $server = new XML_RPC_Server( 246 * array( 247 * 'isan8' => 248 * array( 249 * 'function' => 'is_8', 250 * 'signature' => 251 * array( 252 * array('boolean', 'int'), 253 * array('boolean', 'int', 'boolean'), 254 * array('boolean', 'string'), 255 * array('boolean', 'string', 'boolean'), 256 * ), 257 * 'docstring' => 'Is the value an 8?' 258 * ), 259 * ), 260 * 1, 261 * 0 262 * ); 263 * </code> 264 * 265 * @category Web Services 266 * @package XML_RPC 267 * @author Edd Dumbill <edd@usefulinc.com> 268 * @author Stig Bakken <stig@php.net> 269 * @author Martin Jansen <mj@php.net> 270 * @author Daniel Convissor <danielc@php.net> 271 * @copyright 1999-2001 Edd Dumbill, 2001-2005 The PHP Group 272 * @version Release: 1.4.0 273 * @link http://pear.php.net/package/XML_RPC 274 */ 275 class XML_RPC_Server 276 { 277 /** 278 * The dispatch map, listing the methods this server provides. 279 * @var array 280 */ 281 var $dmap = array(); 282 283 /** 284 * The present response's encoding 285 * @var string 286 * @see XML_RPC_Message::getEncoding() 287 */ 288 var $encoding = ''; 289 290 /** 291 * Debug mode (0 = off, 1 = on) 292 * @var integer 293 */ 294 var $debug = 0; 295 296 /** 297 * The response's HTTP headers 298 * @var string 299 */ 300 var $server_headers = ''; 301 302 /** 303 * The response's XML payload 304 * @var string 305 */ 306 var $server_payload = ''; 307 308 309 /** 310 * Constructor for the XML_RPC_Server class 311 * 312 * @param array $dispMap the dispatch map. An associative array 313 * explaining each function. The keys of the main 314 * array are the procedure names used by the 315 * clients. The value is another associative array 316 * that contains up to three elements: 317 * + The 'function' element's value is the name 318 * of the function or method that gets called. 319 * To define a class' method: 'class::method'. 320 * + The 'signature' element (optional) is an 321 * array describing the return values and 322 * parameters 323 * + The 'docstring' element (optional) is a 324 * string describing what the method does 325 * @param int $serviceNow should the HTTP response be sent now? 326 * (1 = yes, 0 = no) 327 * @param int $debug should debug output be displayed? 328 * (1 = yes, 0 = no) 329 * 330 * @return void 331 */ 332 function XML_RPC_Server($dispMap, $serviceNow = 1, $debug = 0) 333 { 334 global $HTTP_RAW_POST_DATA; 335 336 if ($debug) { 337 $this->debug = 1; 338 } else { 339 $this->debug = 0; 340 } 341 342 $this->dmap = $dispMap; 343 344 if ($serviceNow) { 345 $this->service(); 346 } else { 347 $this->createServerPayload(); 348 $this->createServerHeaders(); 349 } 350 } 351 352 /** 353 * @return string the debug information if debug debug mode is on 354 */ 355 function serializeDebug() 356 { 357 global $XML_RPC_Server_debuginfo, $HTTP_RAW_POST_DATA; 358 359 if ($this->debug) { 360 XML_RPC_Server_debugmsg('vvv POST DATA RECEIVED BY SERVER vvv' . "\n" 361 . $HTTP_RAW_POST_DATA 362 . "\n" . '^^^ END POST DATA ^^^'); 363 } 364 365 if ($XML_RPC_Server_debuginfo != '') { 366 return "<!-- PEAR XML_RPC SERVER DEBUG INFO:\n\n" 367 . preg_replace('/-(?=-)/', '- ', $XML_RPC_Server_debuginfo) 368 . "-->\n"; 369 } else { 370 return ''; 371 } 372 } 373 374 /** 375 * Sends the response 376 * 377 * The encoding and content-type are determined by 378 * XML_RPC_Message::getEncoding() 379 * 380 * @return void 381 * 382 * @uses XML_RPC_Server::createServerPayload(), 383 * XML_RPC_Server::createServerHeaders() 384 */ 385 function service() 386 { 387 if (!$this->server_payload) { 388 $this->createServerPayload(); 389 } 390 if (!$this->server_headers) { 391 $this->createServerHeaders(); 392 } 393 if (!is_array($this->server_headers)) { 394 $this->server_headers = explode("\n", $this->server_headers); 395 } 396 foreach($this->server_headers AS $header) { 397 header($header); 398 } 399 print $this->server_payload; 400 } 401 402 /** 403 * Generates the payload and puts it in the $server_payload property 404 * 405 * @return void 406 * 407 * @uses XML_RPC_Server::parseRequest(), XML_RPC_Server::$encoding, 408 * XML_RPC_Response::serialize(), XML_RPC_Server::serializeDebug() 409 */ 410 function createServerPayload() 411 { 412 $r = $this->parseRequest(); 413 $this->server_payload = '<?xml version="1.0" encoding="' 414 . $this->encoding . '"?>' . "\n" 415 . $this->serializeDebug() 416 . $r->serialize(); 417 } 418 419 /** 420 * Determines the HTTP headers and puts them in the $server_headers 421 * property 422 * 423 * @return boolean TRUE if okay, FALSE if $server_payload isn't set. 424 * 425 * @uses XML_RPC_Server::createServerPayload(), 426 * XML_RPC_Server::$server_headers 427 */ 428 function createServerHeaders() 429 { 430 if (!$this->server_payload) { 431 return false; 432 } 433 $this->server_headers = 'Content-Length: ' 434 . strlen($this->server_payload) . "\r\n" 435 . 'Content-Type: text/xml;' 436 . ' charset=' . $this->encoding; 437 return true; 438 } 439 440 /** 441 * @return array 442 */ 443 function verifySignature($in, $sig) 444 { 445 for ($i = 0; $i < sizeof($sig); $i++) { 446 // check each possible signature in turn 447 $cursig = $sig[$i]; 448 if (sizeof($cursig) == $in->getNumParams() + 1) { 449 $itsOK = 1; 450 for ($n = 0; $n < $in->getNumParams(); $n++) { 451 $p = $in->getParam($n); 452 // print "<!-- $p -->\n"; 453 if ($p->kindOf() == 'scalar') { 454 $pt = $p->scalartyp(); 455 } else { 456 $pt = $p->kindOf(); 457 } 458 // $n+1 as first type of sig is return type 459 if ($pt != $cursig[$n+1]) { 460 $itsOK = 0; 461 $pno = $n+1; 462 $wanted = $cursig[$n+1]; 463 $got = $pt; 464 break; 465 } 466 } 467 if ($itsOK) { 468 return array(1); 469 } 470 } 471 } 472 if (isset($wanted)) { 473 return array(0, "Wanted $wanted}, got $got} at param $pno}"); 474 } else { 475 $allowed = array(); 476 foreach ($sig as $val) { 477 end($val); 478 $allowed[] = key($val); 479 } 480 $allowed = array_unique($allowed); 481 $last = count($allowed) - 1; 482 if ($last > 0) { 483 $allowed[$last] = 'or ' . $allowed[$last]; 484 } 485 return array(0, 486 'Signature permits ' . implode(', ', $allowed) 487 . ' parameters but the request had ' 488 . $in->getNumParams()); 489 } 490 } 491 492 /** 493 * @return object a new XML_RPC_Response object 494 * 495 * @uses XML_RPC_Message::getEncoding(), XML_RPC_Server::$encoding 496 */ 497 function parseRequest($data = '') 498 { 499 global $XML_RPC_xh, $HTTP_RAW_POST_DATA, 500 $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, 501 $XML_RPC_defencoding, $XML_RPC_Server_dmap; 502 503 if ($data == '') { 504 $data = $HTTP_RAW_POST_DATA; 505 } 506 507 $this->encoding = XML_RPC_Message::getEncoding($data); 508 $parser_resource = xml_parser_create($this->encoding); 509 $parser = (int) $parser_resource; 510 511 $XML_RPC_xh[$parser] = array(); 512 $XML_RPC_xh[$parser]['cm'] = 0; 513 $XML_RPC_xh[$parser]['isf'] = 0; 514 $XML_RPC_xh[$parser]['params'] = array(); 515 $XML_RPC_xh[$parser]['method'] = ''; 516 $XML_RPC_xh[$parser]['stack'] = array(); 517 $XML_RPC_xh[$parser]['valuestack'] = array(); 518 519 $plist = ''; 520 521 // decompose incoming XML into request structure 522 523 xml_parser_set_option($parser_resource, XML_OPTION_CASE_FOLDING, true); 524 xml_set_element_handler($parser_resource, 'XML_RPC_se', 'XML_RPC_ee'); 525 xml_set_character_data_handler($parser_resource, 'XML_RPC_cd'); 526 if (!xml_parse($parser_resource, $data, 1)) { 527 // return XML error as a faultCode 528 $r = new XML_RPC_Response(0, 529 $XML_RPC_errxml+xml_get_error_code($parser_resource), 530 sprintf('XML error: %s at line %d', 531 xml_error_string(xml_get_error_code($parser_resource)), 532 xml_get_current_line_number($parser_resource))); 533 xml_parser_free($parser_resource); 534 } elseif ($XML_RPC_xh[$parser]['isf']>1) { 535 $r = new XML_RPC_Response(0, 536 $XML_RPC_err['invalid_request'], 537 $XML_RPC_str['invalid_request'] 538 . ': ' 539 . $XML_RPC_xh[$parser]['isf_reason']); 540 xml_parser_free($parser_resource); 541 } else { 542 xml_parser_free($parser_resource); 543 $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); 544 // now add parameters in 545 for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { 546 // print '<!-- ' . $XML_RPC_xh[$parser]['params'][$i]. "-->\n"; 547 $plist .= "$i - " . var_export($XML_RPC_xh[$parser]['params'][$i], true) . " \n"; 548 $m->addParam($XML_RPC_xh[$parser]['params'][$i]); 549 } 550 XML_RPC_Server_debugmsg($plist); 551 552 // now to deal with the method 553 $methName = $XML_RPC_xh[$parser]['method']; 554 if (strpos($methName, 'system.') === 0) { 555 $dmap = $XML_RPC_Server_dmap; 556 $sysCall = 1; 557 } else { 558 $dmap = $this->dmap; 559 $sysCall = 0; 560 } 561 562 if (isset($dmap[$methName]['function']) 563 && is_string($dmap[$methName]['function']) 564 && strpos($dmap[$methName]['function'], '::') !== false) 565 { 566 $dmap[$methName]['function'] = 567 explode('::', $dmap[$methName]['function']); 568 } 569 570 if (isset($dmap[$methName]['function']) 571 && is_callable($dmap[$methName]['function'])) 572 { 573 // dispatch if exists 574 if (isset($dmap[$methName]['signature'])) { 575 $sr = $this->verifySignature($m, 576 $dmap[$methName]['signature'] ); 577 } 578 if (!isset($dmap[$methName]['signature']) || $sr[0]) { 579 // if no signature or correct signature 580 if ($sysCall) { 581 $r = call_user_func($dmap[$methName]['function'], $this, $m); 582 } else { 583 $r = call_user_func($dmap[$methName]['function'], $m); 584 } 585 if (!is_a($r, 'XML_RPC_Response')) { 586 $r = new XML_RPC_Response(0, $XML_RPC_err['not_response_object'], 587 $XML_RPC_str['not_response_object']); 588 } 589 } else { 590 $r = new XML_RPC_Response(0, $XML_RPC_err['incorrect_params'], 591 $XML_RPC_str['incorrect_params'] 592 . ': ' . $sr[1]); 593 } 594 } else { 595 // else prepare error response 596 $r = new XML_RPC_Response(0, $XML_RPC_err['unknown_method'], 597 $XML_RPC_str['unknown_method']); 598 } 599 } 600 return $r; 601 } 602 603 /** 604 * Echos back the input packet as a string value 605 * 606 * @return void 607 * 608 * Useful for debugging. 609 */ 610 function echoInput() 611 { 612 global $HTTP_RAW_POST_DATA; 613 614 $r = new XML_RPC_Response(0); 615 $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, 'string'); 616 print $r->serialize(); 617 } 618 } 619 620 /* 621 * Local variables: 622 * tab-width: 4 623 * c-basic-offset: 4 624 * c-hanging-comment-ender-p: nil 625 * End: 626 */ 627 628 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sat Nov 24 09:00:37 2007 | par Balluche grâce à PHPXref 0.7 |
|