[ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * @package evocore 4 * @subpackage xmlrpc {@link http://xmlrpc.usefulinc.com/doc/} 5 * @copyright Edd Dumbill <edd@usefulinc.com> (C) 1999-2001 6 */ 7 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 8 9 // by Edd Dumbill (C) 1999-2002 10 // <edd@usefulinc.com> 11 // $Id: _xmlrpc.php,v 1.3 2007/09/11 20:57:52 fplanque Exp $ 12 13 // additional fixes for case of missing xml extension file by Michel Valdrighi <m@tidakada.com> 14 15 // Copyright (c) 1999,2000,2002 Edd Dumbill. 16 // All rights reserved. 17 // 18 // Redistribution and use in source and binary forms, with or without 19 // modification, are permitted provided that the following conditions 20 // are met: 21 // 22 // * Redistributions of source code must retain the above copyright 23 // notice, this list of conditions and the following disclaimer. 24 // 25 // * Redistributions in binary form must reproduce the above 26 // copyright notice, this list of conditions and the following 27 // disclaimer in the documentation and/or other materials provided 28 // with the distribution. 29 // 30 // * Neither the name of the "XML-RPC for PHP" nor the names of its 31 // contributors may be used to endorse or promote products derived 32 // from this software without specific prior written permission. 33 // 34 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 35 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 36 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 37 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 38 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 39 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 40 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 41 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 43 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 45 // OF THE POSSIBILITY OF SUCH DAMAGE. 46 47 # b2 fix. some servers have stupid warnings 48 # error_reporting(0); 49 50 /** 51 * logIO(-) 52 */ 53 if (!function_exists('logIO')) 54 { 55 function logIO($m="",$n="") 56 { 57 return(true); 58 } 59 } 60 61 // Original fix for missing extension file by "Michel Valdrighi" <m@tidakada.com> 62 if(function_exists('xml_parser_create')) 63 { 64 /** 65 * Can we use XML-RPC functionality? 66 * 67 * @constant CANUSEXMLRPC true|string Either === true or holds the error message. 68 */ 69 define( 'CANUSEXMLRPC', TRUE ); 70 } 71 elseif( !(bool)ini_get('enable_dl') || (bool)ini_get('safe_mode')) 72 { // We'll not be able to do dynamic loading (fix by Sakichan) 73 /** 74 * @ignore 75 */ 76 define( 'CANUSEXMLRPC', 'XML extension not loaded, but we cannot dynamically load.' ); 77 } 78 elseif( !empty($WINDIR) ) 79 { // Win 32 fix. From: "Leo West" <lwest@imaginet.fr> 80 if (@dl("php3_xml.dll")) 81 { 82 /** 83 * @ignore 84 */ 85 define( 'CANUSEXMLRPC', true ); 86 } 87 else 88 { 89 /** 90 * @ignore 91 */ 92 define( 'CANUSEXMLRPC', 'Could not load php3_xml.dll!' ); 93 } 94 } 95 else 96 { 97 if (@dl('xml.so')) 98 { 99 /** 100 * @ignore 101 */ 102 define( 'CANUSEXMLRPC', true ); 103 } 104 else 105 { 106 /** 107 * @ignore 108 */ 109 define( 'CANUSEXMLRPC', 'Could not load xml.so!' ); 110 } 111 } 112 113 if( true !== CANUSEXMLRPC ) 114 { 115 return; 116 } 117 118 global $xmlrpcI4; 119 global $xmlrpcInt; 120 global $xmlrpcDouble; 121 global $xmlrpcBoolean; 122 global $xmlrpcString; 123 global $xmlrpcDateTime; 124 global $xmlrpcBase64; 125 global $xmlrpcArray; 126 global $xmlrpcStruct; 127 128 global $xmlrpcTypes; 129 global $xmlrpc_valid_parents; 130 global $xmlEntities; 131 global $xmlrpcerr; 132 global $xmlrpcstr; 133 global $xmlrpc_defencoding; 134 global $xmlrpc_internalencoding; 135 global $xmlrpcName; 136 global $xmlrpcVersion; 137 global $xmlrpcerruser; 138 global $xmlrpcerrxml; 139 global $xmlrpc_backslash; 140 global $_xh; 141 142 $xmlrpcI4='i4'; 143 $xmlrpcInt='int'; 144 $xmlrpcBoolean='boolean'; 145 $xmlrpcDouble='double'; 146 $xmlrpcString='string'; 147 $xmlrpcDateTime='dateTime.iso8601'; 148 $xmlrpcBase64='base64'; 149 $xmlrpcArray='array'; 150 $xmlrpcStruct='struct'; 151 152 $xmlrpcTypes=array( 153 $xmlrpcI4 => 1, 154 $xmlrpcInt => 1, 155 $xmlrpcBoolean => 1, 156 $xmlrpcString => 1, 157 $xmlrpcDouble => 1, 158 $xmlrpcDateTime => 1, 159 $xmlrpcBase64 => 1, 160 $xmlrpcArray => 2, 161 $xmlrpcStruct => 3 162 ); 163 164 $xmlrpc_valid_parents = array( 165 'BOOLEAN' => array('VALUE'), 166 'I4' => array('VALUE'), 167 'INT' => array('VALUE'), 168 'STRING' => array('VALUE'), 169 'DOUBLE' => array('VALUE'), 170 'DATETIME.ISO8601' => array('VALUE'), 171 'BASE64' => array('VALUE'), 172 'ARRAY' => array('VALUE'), 173 'STRUCT' => array('VALUE'), 174 'PARAM' => array('PARAMS'), 175 'METHODNAME' => array('METHODCALL'), 176 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), 177 'MEMBER' => array('STRUCT'), 178 'NAME' => array('MEMBER'), 179 'DATA' => array('ARRAY'), 180 'FAULT' => array('METHODRESPONSE'), 181 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), 182 ); 183 184 $xmlEntities=array( 185 'amp' => '&', 186 'quot' => '"', 187 'lt' => '<', 188 'gt' => '>', 189 'apos' => "'" 190 ); 191 // These are left untranslated because they are sent back to the remote system 192 $xmlrpcerr['unknown_method']=1; 193 $xmlrpcstr['unknown_method']='Unknown method'; 194 $xmlrpcerr['invalid_return']=2; 195 $xmlrpcstr['invalid_return']='Invalid return payload! enable debugging to examine incoming payload.'; 196 $xmlrpcerr['incorrect_params']=3; 197 $xmlrpcstr['incorrect_params']='Incorrect parameters passed to method'; 198 $xmlrpcerr['introspect_unknown']=4; 199 $xmlrpcstr['introspect_unknown']="Can't introspect: method unknown"; 200 $xmlrpcerr['http_error']=5; 201 $xmlrpcstr['http_error']="Didn't receive 200 OK from remote server."; 202 $xmlrpcerr['no_data']=6; 203 $xmlrpcstr['no_data']='No data received from server.'; 204 $xmlrpcerr['no_ssl']=7; 205 $xmlrpcstr['no_ssl']='No SSL support compiled in.'; 206 $xmlrpcerr['curl_fail']=8; 207 $xmlrpcstr['curl_fail']='CURL error'; 208 $xmlrpcerr['invalid_request']=15; 209 $xmlrpcstr['invalid_request']='Invalid request payload'; 210 211 $xmlrpcerr['multicall_notstruct'] = 9; 212 $xmlrpcstr['multicall_notstruct'] = 'system.multicall expected struct'; 213 $xmlrpcerr['multicall_nomethod'] = 10; 214 $xmlrpcstr['multicall_nomethod'] = 'missing methodName'; 215 $xmlrpcerr['multicall_notstring'] = 11; 216 $xmlrpcstr['multicall_notstring'] = 'methodName is not a string'; 217 $xmlrpcerr['multicall_recursion'] = 12; 218 $xmlrpcstr['multicall_recursion'] = 'recursive system.multicall forbidden'; 219 $xmlrpcerr['multicall_noparams'] = 13; 220 $xmlrpcstr['multicall_noparams'] = 'missing params'; 221 $xmlrpcerr['multicall_notarray'] = 14; 222 $xmlrpcstr['multicall_notarray'] = 'params is not an array'; 223 224 // The charset encoding expected by the server for received messages and 225 // by the client for received responses 226 $xmlrpc_defencoding='UTF-8'; 227 // The encoding used by PHP. 228 // String values received will be converted to this. 229 $xmlrpc_internalencoding='ISO-8859-1'; 230 231 $xmlrpcName='XML-RPC for PHP'; 232 $xmlrpcVersion='1.2'; 233 234 // let user errors start at 800 235 $xmlrpcerruser=800; 236 // let XML parse errors start at 100 237 $xmlrpcerrxml=100; 238 239 // formulate backslashes for escaping regexp 240 $xmlrpc_backslash=chr(92).chr(92); 241 242 // used to store state during parsing 243 // quick explanation of components: 244 // ac - used to accumulate values 245 // isf - used to indicate a fault 246 // lv - used to indicate "looking for a value": implements 247 // the logic to allow values with no types to be strings 248 // params - used to store parameters in method calls 249 // method - used to store method name 250 // stack - array with genealogy of xml elements names: 251 // used to validate nesting of xmlrpc elements 252 253 $_xh=array(); 254 255 /** 256 * To help correct communication of non-ascii chars inside strings, regardless 257 * of the charset used when sending requests, parsing them, sending responses 258 * and parsing responses, convert all non-ascii chars present in the message 259 * into their equivalent 'charset entity'. Charset entities enumerated this way 260 * are independent of the charset encoding used to transmit them, and all XML 261 * parsers are bound to understand them. 262 */ 263 function xmlrpc_entity_decode($string) 264 { 265 $top=split('&', $string); 266 $op=''; 267 $i=0; 268 while($i<sizeof($top)) 269 { 270 if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) 271 { 272 $op.=ereg_replace("^[#a-zA-Z0-9]+;", 273 xmlrpc_lookup_entity($regs[1]), 274 $top[$i]); 275 } 276 else 277 { 278 if ($i==0) 279 { 280 $op=$top[$i]; 281 } 282 else 283 { 284 $op.='&' . $top[$i]; 285 } 286 } 287 $i++; 288 } 289 return $op; 290 } 291 292 function xmlrpc_lookup_entity($ent) 293 { 294 global $xmlEntities; 295 296 if (isset($xmlEntities[strtolower($ent)])) 297 { 298 return $xmlEntities[strtolower($ent)]; 299 } 300 if (ereg("^#([0-9]+)$", $ent, $regs)) 301 { 302 return chr($regs[1]); 303 } 304 return '?'; 305 } 306 307 /** 308 * These entities originate from HTML specs (1.1, proposed 2.0, etc), 309 * and are taken directly from php-4.3.1/ext/mbstring/html_entities.c. 310 * Until php provides functionality to translate these entities in its 311 * core library, use this function. 312 */ 313 function xmlrpc_html_entity_xlate($data = '') 314 { 315 $entities = array( 316 " " => " ", 317 "¡" => "¡", 318 "¢" => "¢", 319 "£" => "£", 320 "¤" => "¤", 321 "¥" => "¥", 322 "¦" => "¦", 323 "§" => "§", 324 "¨" => "¨", 325 "©" => "©", 326 "ª" => "ª", 327 "«" => "«", 328 "¬" => "¬", 329 "­" => "­", 330 "®" => "®", 331 "¯" => "¯", 332 "°" => "°", 333 "±" => "±", 334 "²" => "²", 335 "³" => "³", 336 "´" => "´", 337 "µ" => "µ", 338 "¶" => "¶", 339 "·" => "·", 340 "¸" => "¸", 341 "¹" => "¹", 342 "º" => "º", 343 "»" => "»", 344 "¼" => "¼", 345 "½" => "½", 346 "¾" => "¾", 347 "¿" => "¿", 348 "À" => "À", 349 "Á" => "Á", 350 "Â" => "Â", 351 "Ã" => "Ã", 352 "Ä" => "Ä", 353 "Å" => "Å", 354 "Æ" => "Æ", 355 "Ç" => "Ç", 356 "È" => "È", 357 "É" => "É", 358 "Ê" => "Ê", 359 "Ë" => "Ë", 360 "Ì" => "Ì", 361 "Í" => "Í", 362 "Î" => "Î", 363 "Ï" => "Ï", 364 "Ð" => "Ð", 365 "Ñ" => "Ñ", 366 "Ò" => "Ò", 367 "Ó" => "Ó", 368 "Ô" => "Ô", 369 "Õ" => "Õ", 370 "Ö" => "Ö", 371 "×" => "×", 372 "Ø" => "Ø", 373 "Ù" => "Ù", 374 "Ú" => "Ú", 375 "Û" => "Û", 376 "Ü" => "Ü", 377 "Ý" => "Ý", 378 "Þ" => "Þ", 379 "ß" => "ß", 380 "à" => "à", 381 "á" => "á", 382 "â" => "â", 383 "ã" => "ã", 384 "ä" => "ä", 385 "å" => "å", 386 "æ" => "æ", 387 "ç" => "ç", 388 "è" => "è", 389 "é" => "é", 390 "ê" => "ê", 391 "ë" => "ë", 392 "ì" => "ì", 393 "í" => "í", 394 "î" => "î", 395 "ï" => "ï", 396 "ð" => "ð", 397 "ñ" => "ñ", 398 "ò" => "ò", 399 "ó" => "ó", 400 "ô" => "ô", 401 "õ" => "õ", 402 "ö" => "ö", 403 "÷" => "÷", 404 "ø" => "ø", 405 "ù" => "ù", 406 "ú" => "ú", 407 "û" => "û", 408 "ü" => "ü", 409 "ý" => "ý", 410 "þ" => "þ", 411 "ÿ" => "ÿ", 412 "Œ" => "Œ", 413 "œ" => "œ", 414 "Š" => "Š", 415 "š" => "š", 416 "Ÿ" => "Ÿ", 417 "ƒ" => "ƒ", 418 "ˆ" => "ˆ", 419 "˜" => "˜", 420 "Α" => "Α", 421 "Β" => "Β", 422 "Γ" => "Γ", 423 "Δ" => "Δ", 424 "Ε" => "Ε", 425 "Ζ" => "Ζ", 426 "Η" => "Η", 427 "Θ" => "Θ", 428 "Ι" => "Ι", 429 "Κ" => "Κ", 430 "Λ" => "Λ", 431 "Μ" => "Μ", 432 "Ν" => "Ν", 433 "Ξ" => "Ξ", 434 "Ο" => "Ο", 435 "Π" => "Π", 436 "Ρ" => "Ρ", 437 "Σ" => "Σ", 438 "Τ" => "Τ", 439 "Υ" => "Υ", 440 "Φ" => "Φ", 441 "Χ" => "Χ", 442 "Ψ" => "Ψ", 443 "Ω" => "Ω", 444 "β" => "β", 445 "γ" => "γ", 446 "δ" => "δ", 447 "ε" => "ε", 448 "ζ" => "ζ", 449 "η" => "η", 450 "θ" => "θ", 451 "ι" => "ι", 452 "κ" => "κ", 453 "λ" => "λ", 454 "μ" => "μ", 455 "ν" => "ν", 456 "ξ" => "ξ", 457 "ο" => "ο", 458 "π" => "π", 459 "ρ" => "ρ", 460 "ς" => "ς", 461 "σ" => "σ", 462 "τ" => "τ", 463 "υ" => "υ", 464 "φ" => "φ", 465 "χ" => "χ", 466 "ψ" => "ψ", 467 "ω" => "ω", 468 "ϑ" => "ϑ", 469 "ϒ" => "ϒ", 470 "ϖ" => "ϖ", 471 " " => " ", 472 " " => " ", 473 " " => " ", 474 "‌" => "‌", 475 "‍" => "‍", 476 "‎" => "‎", 477 "‏" => "‏", 478 "–" => "–", 479 "—" => "—", 480 "‘" => "‘", 481 "’" => "’", 482 "‚" => "‚", 483 "“" => "“", 484 "”" => "”", 485 "„" => "„", 486 "†" => "†", 487 "‡" => "‡", 488 "•" => "•", 489 "…" => "…", 490 "‰" => "‰", 491 "′" => "′", 492 "″" => "″", 493 "‹" => "‹", 494 "›" => "›", 495 "‾" => "‾", 496 "⁄" => "⁄", 497 "€" => "€", 498 "℘" => "℘", 499 "ℑ" => "ℑ", 500 "ℜ" => "ℜ", 501 "™" => "™", 502 "ℵ" => "ℵ", 503 "←" => "←", 504 "↑" => "↑", 505 "→" => "→", 506 "↓" => "↓", 507 "↔" => "↔", 508 "↵" => "↵", 509 "⇐" => "⇐", 510 "⇑" => "⇑", 511 "⇒" => "⇒", 512 "⇓" => "⇓", 513 "⇔" => "⇔", 514 "∀" => "∀", 515 "∂" => "∂", 516 "∃" => "∃", 517 "∅" => "∅", 518 "∇" => "∇", 519 "∈" => "∈", 520 "∉" => "∉", 521 "∋" => "∋", 522 "∏" => "∏", 523 "∑" => "∑", 524 "−" => "−", 525 "∗" => "∗", 526 "√" => "√", 527 "∝" => "∝", 528 "∞" => "∞", 529 "∠" => "∠", 530 "∧" => "∧", 531 "∨" => "∨", 532 "∩" => "∩", 533 "∪" => "∪", 534 "∫" => "∫", 535 "∴" => "∴", 536 "∼" => "∼", 537 "≅" => "≅", 538 "≈" => "≈", 539 "≠" => "≠", 540 "≡" => "≡", 541 "≤" => "≤", 542 "≥" => "≥", 543 "⊂" => "⊂", 544 "⊃" => "⊃", 545 "⊄" => "⊄", 546 "⊆" => "⊆", 547 "⊇" => "⊇", 548 "⊕" => "⊕", 549 "⊗" => "⊗", 550 "⊥" => "⊥", 551 "⋅" => "⋅", 552 "⌈" => "⌈", 553 "⌉" => "⌉", 554 "⌊" => "⌊", 555 "⌋" => "⌋", 556 "⟨" => "〈", 557 "⟩" => "〉", 558 "◊" => "◊", 559 "♠" => "♠", 560 "♣" => "♣", 561 "♥" => "♥", 562 "♦" => "♦"); 563 return strtr($data, $entities); 564 } 565 566 function xmlrpc_encode_entitites($data) 567 { 568 $length = strlen($data); 569 $escapeddata = ""; 570 for($position = 0; $position < $length; $position++) 571 { 572 $character = substr($data, $position, 1); 573 $code = Ord($character); 574 switch($code) { 575 case 34: 576 $character = """; 577 break; 578 case 38: 579 $character = "&"; 580 break; 581 case 39: 582 $character = "'"; 583 break; 584 case 60: 585 $character = "<"; 586 break; 587 case 62: 588 $character = ">"; 589 break; 590 default: 591 if ($code < 32 || $code > 159) 592 $character = ("&#".strval($code).";"); 593 break; 594 } 595 $escapeddata .= $character; 596 } 597 return $escapeddata; 598 } 599 600 function xmlrpc_se($parser, $name, $attrs) 601 { 602 global $_xh, $xmlrpcDateTime, $xmlrpcString, $xmlrpc_valid_parents; 603 604 // if invalid xmlrpc already detected, skip all processing 605 if ($_xh[$parser]['isf'] < 2) 606 { 607 608 // check for correct element nesting 609 // top level element can only be of 2 types 610 if (count($_xh[$parser]['stack']) == 0) 611 { 612 if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') 613 { 614 $_xh[$parser]['isf'] = 2; 615 $_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; 616 return; 617 } 618 } 619 else 620 { 621 // not top level element: see if parent is OK 622 if (!in_array($_xh[$parser]['stack'][0], $xmlrpc_valid_parents[$name])) 623 { 624 $_xh[$parser]['isf'] = 2; 625 $_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$_xh[$parser]['stack'][0]}"; 626 return; 627 } 628 } 629 630 switch($name) 631 { 632 case 'STRUCT': 633 case 'ARRAY': 634 //$_xh[$parser]['st'].='array('; 635 //$_xh[$parser]['cm']++; 636 // this last line turns quoting off 637 // this means if we get an empty array we'll 638 // simply get a bit of whitespace in the eval 639 //$_xh[$parser]['qt']=0; 640 641 // create an empty array to hold child values, and push it onto appropriate stack 642 $cur_val = array(); 643 $cur_val['values'] = array(); 644 $cur_val['type'] = $name; 645 array_unshift($_xh[$parser]['valuestack'], $cur_val); 646 break; 647 case 'METHODNAME': 648 case 'NAME': 649 //$_xh[$parser]['st'].='"'; 650 $_xh[$parser]['ac']=''; 651 break; 652 case 'FAULT': 653 $_xh[$parser]['isf']=1; 654 break; 655 case 'PARAM': 656 //$_xh[$parser]['st']=''; 657 // clear value, so we can check later if no value will passed for this param/member 658 $_xh[$parser]['value']=null; 659 break; 660 case 'VALUE': 661 //$_xh[$parser]['st'].='new xmlrpcval('; 662 // look for a value: if this is still true by the 663 // time we reach the end tag for value then the type is string 664 // by implication 665 $_xh[$parser]['vt']='value'; 666 $_xh[$parser]['ac']=''; 667 //$_xh[$parser]['qt']=0; 668 $_xh[$parser]['lv']=1; 669 break; 670 case 'I4': 671 case 'INT': 672 case 'STRING': 673 case 'BOOLEAN': 674 case 'DOUBLE': 675 case 'DATETIME.ISO8601': 676 case 'BASE64': 677 if ($_xh[$parser]['vt']!='value') 678 { 679 //two data elements inside a value: an error occurred! 680 $_xh[$parser]['isf'] = 2; 681 $_xh[$parser]['isf_reason'] = "$name element following a {$_xh[$parser]['vt']} element inside a single value"; 682 return; 683 } 684 685 // reset the accumulator 686 $_xh[$parser]['ac']=''; 687 688 /*if ($name=='DATETIME.ISO8601' || $name=='STRING') 689 { 690 $_xh[$parser]['qt']=1; 691 if ($name=='DATETIME.ISO8601') 692 { 693 $_xh[$parser]['vt']=$xmlrpcDateTime; 694 } 695 } 696 elseif ($name=='BASE64') 697 { 698 $_xh[$parser]['qt']=2; 699 } 700 else 701 { 702 // No quoting is required here -- but 703 // at the end of the element we must check 704 // for data format errors. 705 $_xh[$parser]['qt']=0; 706 }*/ 707 break; 708 case 'MEMBER': 709 //$_xh[$parser]['ac']=''; 710 // avoid warnings later on if no NAME is found before VALUE inside 711 // a struct member predefining member name as NULL 712 $_xh[$parser]['valuestack'][0]['name'] = ''; 713 // clear value, so we can check later if no value will passed for this param/member 714 $_xh[$parser]['value']=null; 715 break; 716 case 'DATA': 717 case 'METHODCALL': 718 case 'METHODRESPONSE': 719 case 'PARAMS': 720 // valid elements that add little to processing 721 break; 722 default: 723 /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!! 724 $_xh[$parser]['isf'] = 2; 725 $_xh[$parser]['isf_reason'] = "found not-xmlrpc xml element $name"; 726 break; 727 } 728 729 // Save current element name to stack, to validate nesting 730 array_unshift($_xh[$parser]['stack'], $name); 731 732 if ($name!='VALUE') 733 { 734 $_xh[$parser]['lv']=0; 735 } 736 } 737 } 738 739 function xmlrpc_ee($parser, $name) 740 { 741 global $_xh,$xmlrpcTypes,$xmlrpcString,$xmlrpcDateTime; 742 743 if ($_xh[$parser]['isf'] < 2) 744 { 745 746 // push this element name from stack 747 // NB: if XML validates, correct opening/closing is guaranteed and 748 // we do not have to check for $name == $curr_elem. 749 // we also checked for proper nesting at start of elements... 750 $curr_elem = array_shift($_xh[$parser]['stack']); 751 752 switch($name) 753 { 754 case 'STRUCT': 755 case 'ARRAY': 756 //if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',') 757 //{ 758 // $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1); 759 //} 760 //$_xh[$parser]['st'].=')'; 761 762 // fetch out of stack array of values, and promote it to current value 763 $cur_val = array_shift($_xh[$parser]['valuestack']); 764 $_xh[$parser]['value'] = $cur_val['values']; 765 766 $_xh[$parser]['vt']=strtolower($name); 767 //$_xh[$parser]['cm']--; 768 break; 769 case 'NAME': 770 //$_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => '; 771 $_xh[$parser]['valuestack'][0]['name'] = $_xh[$parser]['ac']; 772 break; 773 case 'BOOLEAN': 774 case 'I4': 775 case 'INT': 776 case 'STRING': 777 case 'DOUBLE': 778 case 'DATETIME.ISO8601': 779 case 'BASE64': 780 $_xh[$parser]['vt']=strtolower($name); 781 //if ($_xh[$parser]['qt']==1) 782 if ($name=='STRING') 783 { 784 // we use double quotes rather than single so backslashification works OK 785 //$_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; 786 $_xh[$parser]['value']=$_xh[$parser]['ac']; 787 } 788 elseif ($name=='DATETIME.ISO8601') 789 { 790 $_xh[$parser]['vt']=$xmlrpcDateTime; 791 $_xh[$parser]['value']=$_xh[$parser]['ac']; 792 } 793 elseif ($name=='BASE64') 794 { 795 //$_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")'; 796 797 ///@todo check for failure of base64 decoding / catch warnings 798 $_xh[$parser]['value']=base64_decode($_xh[$parser]['ac']); 799 } 800 elseif ($name=='BOOLEAN') 801 { 802 // special case here: we translate boolean 1 or 0 into PHP 803 // constants true or false 804 // NB: this simple checks helps a lot sanitizing input, ie no 805 // security problems around here 806 if ($_xh[$parser]['ac']=='1') 807 { 808 //$_xh[$parser]['ac']='true'; 809 $_xh[$parser]['value']=true; 810 } 811 else 812 { 813 //$_xh[$parser]['ac']='false'; 814 // log if receiveing something strange, even though we set the value to false anyway 815 if ($_xh[$parser]['ac']!='0') 816 error_log('XML-RPC: invalid value received in BOOLEAN: '.$_xh[$parser]['ac']); 817 $_xh[$parser]['value']=false; 818 } 819 //$_xh[$parser]['st'].=$_xh[$parser]['ac']; 820 } 821 elseif ($name=='DOUBLE') 822 { 823 // we have a DOUBLE 824 // we must check that only 0123456789-.<space> are characters here 825 if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$", $_xh[$parser]['ac'])) 826 { 827 // TODO: find a better way of throwing an error 828 // than this! 829 error_log('XML-RPC: non numeric value received in DOUBLE: '.$_xh[$parser]['ac']); 830 //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; 831 $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND'; 832 } 833 else 834 { 835 // it's ok, add it on 836 //$_xh[$parser]['st'].=(double)$_xh[$parser]['ac']; 837 $_xh[$parser]['value']=(double)$_xh[$parser]['ac']; 838 } 839 } 840 else 841 { 842 // we have an I4/INT 843 // we must check that only 0123456789-<space> are characters here 844 if (!ereg("^[+-]?[0123456789 \\t]+$", $_xh[$parser]['ac'])) 845 { 846 // TODO: find a better way of throwing an error 847 // than this! 848 error_log('XML-RPC: non numeric value received in INT: '.$_xh[$parser]['ac']); 849 //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; 850 $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND'; 851 } 852 else 853 { 854 // it's ok, add it on 855 //$_xh[$parser]['st'].=(int)$_xh[$parser]['ac']; 856 $_xh[$parser]['value']=(int)$_xh[$parser]['ac']; 857 } 858 } 859 $_xh[$parser]['ac']=''; 860 //$_xh[$parser]['qt']=0; 861 $_xh[$parser]['lv']=3; // indicate we've found a value 862 break; 863 case 'VALUE': 864 // This if() detects if no scalar was inside <VALUE></VALUE> 865 if ($_xh[$parser]['vt']=='value') 866 { 867 $_xh[$parser]['value']=$_xh[$parser]['ac']; 868 $_xh[$parser]['vt']=$xmlrpcString; 869 } 870 /*if (strlen($_xh[$parser]['ac'])>0 && 871 $_xh[$parser]['vt']==$xmlrpcString) 872 { 873 $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; 874 } 875 // This if() detects if no scalar was inside <VALUE></VALUE> 876 // and pads an empty ''. 877 if($_xh[$parser]['st'][strlen($_xh[$parser]['st'])-1] == '(') 878 { 879 $_xh[$parser]['st'].= '""'; 880 } 881 // G. Giunta 2005/03/12 save some chars in the reconstruction of string vals... 882 if ($_xh[$parser]['vt'] != $xmlrpcString) 883 $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')"; 884 else 885 $_xh[$parser]['st'].=")"; 886 if ($_xh[$parser]['cm']) 887 { 888 $_xh[$parser]['st'].=','; 889 }*/ 890 891 // build the xmlrpc val out of the data received, and substitute it 892 $temp = new xmlrpcval($_xh[$parser]['value'], $_xh[$parser]['vt']); 893 // check if we are inside an array or struct: 894 // if value just built is inside an array, let's move it into array on the stack 895 if (count($_xh[$parser]['valuestack']) && $_xh[$parser]['valuestack'][0]['type']=='ARRAY') 896 { 897 $_xh[$parser]['valuestack'][0]['values'][] = $temp; 898 } 899 else 900 { 901 $_xh[$parser]['value'] = $temp; 902 } 903 break; 904 case 'MEMBER': 905 $_xh[$parser]['ac']=''; 906 //$_xh[$parser]['qt']=0; 907 // add to array in the stack the last element built 908 // unless no VALUE was found 909 if ($_xh[$parser]['value']) 910 $_xh[$parser]['valuestack'][0]['values'][$_xh[$parser]['valuestack'][0]['name']] = $_xh[$parser]['value']; 911 else 912 error_log('XML-RPC: missing VALUE inside STRUCT in received xml'); 913 break; 914 case 'DATA': 915 $_xh[$parser]['ac']=''; 916 //$_xh[$parser]['qt']=0; 917 break; 918 case 'PARAM': 919 //$_xh[$parser]['params'][]=$_xh[$parser]['st']; 920 if ($_xh[$parser]['value']) 921 $_xh[$parser]['params'][]=$_xh[$parser]['value']; 922 else 923 error_log('XML-RPC: missing VALUE inside PARAM in received xml'); 924 break; 925 case 'METHODNAME': 926 $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", '', $_xh[$parser]['ac']); 927 break; 928 case 'PARAMS': 929 case 'FAULT': 930 case 'METHODCALL': 931 case 'METHORESPONSE': 932 break; 933 default: 934 // End of INVALID ELEMENT! 935 // shall we add an assert here for unreachable code??? 936 break; 937 } 938 939 // if it's a valid type name, set the type 940 /*if (isset($xmlrpcTypes[strtolower($name)])) 941 { 942 $_xh[$parser]['vt']=strtolower($name); 943 }*/ 944 945 } 946 947 } 948 949 function xmlrpc_cd($parser, $data) 950 { 951 global $_xh, $xmlrpc_backslash; 952 953 //if (ereg("^[\n\r \t]+$", $data)) return; 954 // print "adding [${data}]\n"; 955 956 // skip processing if xml fault already detected 957 if ($_xh[$parser]['isf'] < 2) 958 { 959 if ($_xh[$parser]['lv']!=3) 960 { 961 // "lookforvalue==3" means that we've found an entire value 962 // and should discard any further character data 963 if ($_xh[$parser]['lv']==1) 964 { 965 // if we've found text and we're just in a <value> then 966 // turn quoting on, as this will be a string 967 //$_xh[$parser]['qt']=1; 968 // and say we've found a value 969 $_xh[$parser]['lv']=2; 970 } 971 if(!@isset($_xh[$parser]['ac'])) 972 { 973 $_xh[$parser]['ac'] = ''; 974 } 975 //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); 976 $_xh[$parser]['ac'].=$data; 977 } 978 } 979 } 980 981 function xmlrpc_dh($parser, $data) 982 { 983 global $_xh, $xmlrpc_backslash; 984 985 // skip processing if xml fault already detected 986 if ($parser[$_xh]['isf'] < 2) 987 { 988 if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') 989 { 990 if ($_xh[$parser]['lv']==1) 991 { 992 //$_xh[$parser]['qt']=1; 993 $_xh[$parser]['lv']=2; 994 } 995 //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); 996 $_xh[$parser]['ac'].=$data; 997 } 998 } 999 } 1000 1001 /** 1002 * @package evocore 1003 * @subpackage xmlrpc 1004 */ 1005 class xmlrpc_client 1006 { 1007 var $path; 1008 var $server; 1009 var $port; 1010 var $errno; 1011 var $errstr; 1012 var $debug=0; 1013 var $username=''; 1014 var $password=''; 1015 var $cert=''; 1016 var $certpass=''; 1017 var $verifypeer=1; 1018 var $verifyhost=1; 1019 var $no_multicall=false; 1020 1021 function xmlrpc_client($path, $server, $port=0) 1022 { 1023 global $debug_xmlrpc_logging; 1024 1025 $this->port=$port; $this->server=$server; $this->path=$path; 1026 $this->debug = $debug_xmlrpc_logging; 1027 } 1028 1029 function setDebug($in) 1030 { 1031 if ($in) 1032 { 1033 $this->debug=1; 1034 } 1035 else 1036 { 1037 $this->debug=0; 1038 } 1039 } 1040 1041 function setCredentials($u, $p) 1042 { 1043 $this->username=$u; 1044 $this->password=$p; 1045 } 1046 1047 function setCertificate($cert, $certpass) 1048 { 1049 $this->cert = $cert; 1050 $this->certpass = $certpass; 1051 } 1052 1053 function setSSLVerifyPeer($i) 1054 { 1055 $this->verifypeer = $i; 1056 } 1057 1058 function setSSLVerifyHost($i) 1059 { 1060 $this->verifyhost = $i; 1061 } 1062 1063 /* 1064 * xmlrpc_client->send(-) 1065 */ 1066 function send($msg, $timeout=0, $method='http') 1067 { 1068 if (is_array($msg)) 1069 { 1070 // $msg is an array of xmlrpcmsg's 1071 return $this->multicall($msg, $timeout, $method); 1072 } 1073 1074 // where msg is an xmlrpcmsg 1075 $msg->debug=$this->debug; 1076 1077 if ($method == 'https') 1078 { 1079 return $this->sendPayloadHTTPS($msg, 1080 $this->server, 1081 $this->port, $timeout, 1082 $this->username, $this->password, 1083 $this->cert, 1084 $this->certpass); 1085 } 1086 else 1087 { 1088 return $this->sendPayloadHTTP10($msg, $this->server, $this->port, 1089 $timeout, $this->username, 1090 $this->password); 1091 } 1092 } 1093 1094 function sendPayloadHTTP10($msg, $server, $port, $timeout=0,$username='', $password='') 1095 { 1096 global $xmlrpcerr, $xmlrpcstr, $xmlrpcName, $xmlrpcVersion, $xmlrpc_defencoding; 1097 if ($port==0) 1098 { 1099 $port=80; 1100 } 1101 if($timeout>0) 1102 { 1103 $fp=@fsockopen($server, $port,$this->errno, $this->errstr, $timeout); 1104 } 1105 else 1106 { 1107 $fp=@fsockopen($server, $port,$this->errno, $this->errstr); 1108 } 1109 if ($fp) 1110 { 1111 if( $timeout>0 ) 1112 { 1113 if( function_exists('stream_set_timeout') ) 1114 { // PHP 4.3.0: 1115 stream_set_timeout($fp, $timeout); 1116 } 1117 elseif( function_exists('socket_set_timeout') ) 1118 { // PHP 4: 1119 socket_set_timeout($fp, $timeout); 1120 } 1121 } 1122 } 1123 else 1124 { 1125 $this->errstr='Connect error'; 1126 $r=new xmlrpcresp(0, $xmlrpcerr['http_error'],$xmlrpcstr['http_error']); 1127 return $r; 1128 } 1129 // Only create the payload if it was not created previously 1130 if(empty($msg->payload)) 1131 { 1132 $msg->createPayload(); 1133 } 1134 1135 // thanks to Grant Rauscher <grant7@firstworld.net> 1136 // for this 1137 $credentials=''; 1138 if ($username!='') 1139 { 1140 $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n"; 1141 } 1142 1143 $op= "POST " . $this->path. " HTTP/1.0\r\n" . 1144 "User-Agent: " . $xmlrpcName . " " . $xmlrpcVersion . "\r\n" . 1145 "Host: ". $server . "\r\n" . 1146 $credentials . 1147 "Accept-Charset: " . $xmlrpc_defencoding . "\r\n" . 1148 "Content-Type: text/xml\r\nContent-Length: " . 1149 strlen($msg->payload) . "\r\n\r\n" . 1150 $msg->payload; 1151 1152 if (!fputs($fp, $op, strlen($op))) 1153 { 1154 $this->errstr='Write error'; 1155 $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']); 1156 return $r; 1157 } 1158 $resp=$msg->parseResponseFile($fp); 1159 fclose($fp); 1160 return $resp; 1161 } 1162 1163 // contributed by Justin Miller <justin@voxel.net> 1164 // requires curl to be built into PHP 1165 function sendPayloadHTTPS($msg, $server, $port, $timeout=0,$username='', $password='', $cert='',$certpass='') 1166 { 1167 global $xmlrpcerr, $xmlrpcstr, $xmlrpcVersion, $xmlrpc_internalencoding; 1168 if ($port == 0) 1169 { 1170 $port = 443; 1171 } 1172 1173 // Only create the payload if it was not created previously 1174 if(empty($msg->payload)) 1175 { 1176 $msg->createPayload(); 1177 } 1178 1179 if (!function_exists('curl_init')) 1180 { 1181 $this->errstr='SSL unavailable on this install'; 1182 $r=new xmlrpcresp(0, $xmlrpcerr['no_ssl'], $xmlrpcstr['no_ssl']); 1183 return $r; 1184 } 1185 1186 $curl = curl_init('https://' . $server . ':' . $port . $this->path); 1187 1188 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 1189 // results into variable 1190 if ($this->debug) 1191 { 1192 curl_setopt($curl, CURLOPT_VERBOSE, 1); 1193 } 1194 curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC '.$xmlrpcVersion); 1195 // required for XMLRPC 1196 curl_setopt($curl, CURLOPT_POST, 1); 1197 // post the data 1198 curl_setopt($curl, CURLOPT_POSTFIELDS, $msg->payload); 1199 // the data 1200 curl_setopt($curl, CURLOPT_HEADER, 1); 1201 // return the header too 1202 curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept-Charset: '.$xmlrpc_internalencoding)); 1203 // whether to verify remote host's cert 1204 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer); 1205 // whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used 1206 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost); 1207 // required for XMLRPC 1208 if ($timeout) 1209 { 1210 curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1); 1211 } 1212 // timeout is borked 1213 if ($username && $password) 1214 { 1215 curl_setopt($curl, CURLOPT_USERPWD,"$username:$password"); 1216 } 1217 // set auth stuff 1218 if ($cert) 1219 { 1220 curl_setopt($curl, CURLOPT_SSLCERT, $cert); 1221 } 1222 // set cert file 1223 if ($certpass) 1224 { 1225 curl_setopt($curl, CURLOPT_SSLCERTPASSWD,$certpass); 1226 } 1227 // set cert password 1228 1229 $result = curl_exec($curl); 1230 1231 if (!$result) 1232 { 1233 $this->errstr='no response'; 1234 $resp=new xmlrpcresp(0, $xmlrpcerr['curl_fail'], $xmlrpcstr['curl_fail']. ': '. curl_error($curl)); 1235 curl_close($curl); 1236 } 1237 else 1238 { 1239 curl_close($curl); 1240 $resp = $msg->parseResponse($result); 1241 } 1242 return $resp; 1243 } 1244 1245 function multicall($msgs, $timeout=0, $method='http') 1246 { 1247 $results = false; 1248 1249 if (! $this->no_multicall) 1250 { 1251 $results = $this->_try_multicall($msgs, $timeout, $method); 1252 /* TODO - this is not php3-friendly */ 1253 // if($results !== false) 1254 if(is_array($results)) 1255 { 1256 // Either the system.multicall succeeded, or the send 1257 // failed (e.g. due to HTTP timeout). In either case, 1258 // we're done for now. 1259 return $results; 1260 } 1261 else 1262 { 1263 // system.multicall unsupported by server, 1264 // don't try it next time... 1265 $this->no_multicall = true; 1266 } 1267 } 1268 1269 // system.multicall is unupported by server: 1270 // Emulate multicall via multiple requests 1271 $results = array(); 1272 //foreach($msgs as $msg) 1273 @reset($msgs); 1274 while(list(,$msg) = @each($msgs)) 1275 { 1276 $results[] = $this->send($msg, $timeout, $method); 1277 } 1278 return $results; 1279 } 1280 1281 // Attempt to boxcar $msgs via system.multicall. 1282 function _try_multicall($msgs, $timeout, $method) 1283 { 1284 // Construct multicall message 1285 $calls = array(); 1286 //foreach($msgs as $msg) 1287 @reset($msgs); 1288 while(list(,$msg) = @each($msgs)) 1289 { 1290 $call['methodName'] = new xmlrpcval($msg->method(),'string'); 1291 $numParams = $msg->getNumParams(); 1292 $params = array(); 1293 for ($i = 0; $i < $numParams; $i++) 1294 { 1295 $params[$i] = $msg->getParam($i); 1296 } 1297 $call['params'] = new xmlrpcval($params, 'array'); 1298 $calls[] = new xmlrpcval($call, 'struct'); 1299 } 1300 $multicall = new xmlrpcmsg('system.multicall'); 1301 $multicall->addParam(new xmlrpcval($calls, 'array')); 1302 1303 // Attempt RPC call 1304 $result = $this->send($multicall, $timeout, $method); 1305 if(!is_object($result)) 1306 { 1307 return ($result || 0); // transport failed 1308 } 1309 1310 if($result->faultCode() != 0) 1311 { 1312 return false; // system.multicall failed 1313 } 1314 1315 // Unpack responses. 1316 $rets = $result->value(); 1317 if($rets->kindOf() != 'array') 1318 { 1319 return false; // bad return type from system.multicall 1320 } 1321 $numRets = $rets->arraysize(); 1322 if($numRets != count($msgs)) 1323 { 1324 return false; // wrong number of return values. 1325 } 1326 1327 $response = array(); 1328 for ($i = 0; $i < $numRets; $i++) 1329 { 1330 $val = $rets->arraymem($i); 1331 switch ($val->kindOf()) 1332 { 1333 case 'array': 1334 if($val->arraysize() != 1) 1335 { 1336 return false; // Bad value 1337 } 1338 // Normal return value 1339 $response[$i] = new xmlrpcresp($val->arraymem(0)); 1340 break; 1341 case 'struct': 1342 $code = $val->structmem('faultCode'); 1343 if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int') 1344 { 1345 return false; 1346 } 1347 $str = $val->structmem('faultString'); 1348 if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string') 1349 { 1350 return false; 1351 } 1352 $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval()); 1353 break; 1354 default: 1355 return false; 1356 } 1357 } 1358 return $response; 1359 } 1360 } // end class xmlrpc_client 1361 1362 /** 1363 * @package evocore 1364 * @subpackage xmlrpc 1365 */ 1366 class xmlrpcresp 1367 { 1368 var $val = 0; 1369 var $errno = 0; 1370 var $errstr = ''; 1371 var $hdrs = array(); 1372 1373 function xmlrpcresp($val, $fcode = 0, $fstr = '') 1374 { 1375 if ($fcode != 0) 1376 { 1377 // error 1378 $this->errno = $fcode; 1379 $this->errstr = $fstr; 1380 //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later. 1381 } 1382 elseif (!is_object($val)) 1383 { 1384 // programmer error 1385 error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to xmlrpcresp. Defaulting to empty value."); 1386 $this->val = new xmlrpcval(); 1387 } 1388 else 1389 { 1390 // success 1391 $this->val = $val; 1392 } 1393 } 1394 1395 function faultCode() 1396 { 1397 return $this->errno; 1398 } 1399 1400 function faultString() 1401 { 1402 return $this->errstr; 1403 } 1404 1405 function value() 1406 { 1407 return $this->val; 1408 } 1409 1410 function serialize() 1411 { 1412 $result = "<methodResponse>\n"; 1413 if ($this->errno) 1414 { 1415 // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients 1416 $result .= '<fault> 1417 <value> 1418 <struct> 1419 <member> 1420 <name>faultCode</name> 1421 <value><int>' . $this->errno . '</int></value> 1422 </member> 1423 <member> 1424 <name>faultString</name> 1425 <value><string>' . xmlrpc_encode_entitites($this->errstr) . '</string></value> 1426 </member> 1427 </struct> 1428 </value> 1429 </fault>'; 1430 } 1431 else 1432 { 1433 $result .= "<params>\n<param>\n" . 1434 $this->val->serialize() . 1435 "</param>\n</params>"; 1436 } 1437 $result .= "\n</methodResponse>"; 1438 return $result; 1439 } 1440 } 1441 1442 /** 1443 * @package evocore 1444 * @subpackage xmlrpc 1445 */ 1446 class xmlrpcmsg 1447 { 1448 var $payload; 1449 var $methodname; 1450 var $params=array(); 1451 var $debug=0; 1452 1453 function xmlrpcmsg($meth, $pars=0) 1454 { 1455 $this->methodname=$meth; 1456 if (is_array($pars) && sizeof($pars)>0) 1457 { 1458 for($i=0; $i<sizeof($pars); $i++) 1459 { 1460 $this->addParam($pars[$i]); 1461 } 1462 } 1463 } 1464 1465 function xml_header() 1466 { 1467 // TODO: handle encoding 1468 // return "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?".">\n<methodCall>\n"; 1469 1470 return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n"; 1471 } 1472 1473 function xml_footer() 1474 { 1475 return "</methodCall>\n"; 1476 } 1477 1478 function createPayload() 1479 { 1480 $this->payload=$this->xml_header(); 1481 $this->payload.='<methodName>' . $this->methodname . "</methodName>\n"; 1482 // if (sizeof($this->params)) { 1483 $this->payload.="<params>\n"; 1484 for($i=0; $i<sizeof($this->params); $i++) 1485 { 1486 $p=$this->params[$i]; 1487 $this->payload.="<param>\n" . $p->serialize() . 1488 "</param>\n"; 1489 } 1490 $this->payload.="</params>\n"; 1491 // } 1492 $this->payload.=$this->xml_footer(); 1493 //$this->payload=str_replace("\n", "\r\n", $this->payload); 1494 } 1495 1496 function method($meth='') 1497 { 1498 if ($meth!='') 1499 { 1500 $this->methodname=$meth; 1501 } 1502 return $this->methodname; 1503 } 1504 1505 function serialize() 1506 { 1507 $this->createPayload(); 1508 return $this->payload; 1509 } 1510 1511 function addParam($par) { $this->params[]=$par; } 1512 function getParam($i) { return $this->params[$i]; } 1513 function getNumParams() { return sizeof($this->params); } 1514 1515 function parseResponseFile($fp) 1516 { 1517 $ipd=''; 1518 while($data=fread($fp, 32768)) 1519 { 1520 $ipd.=$data; 1521 } 1522 return $this->parseResponse($ipd); 1523 } 1524 1525 function parseResponse($data='') 1526 { 1527 global $_xh,$xmlrpcerr,$xmlrpcstr; 1528 global $xmlrpc_defencoding, $xmlrpc_internalencoding; 1529 1530 $hdrfnd = 0; 1531 if($this->debug) 1532 { 1533 //by maHo, replaced htmlspecialchars with htmlentities 1534 print "<PRE>---GOT---\n" . htmlentities($data) . "\n---END---\n</PRE>"; 1535 } 1536 1537 if($data == '') 1538 { 1539 error_log('No response received from server.'); 1540 $r = new xmlrpcresp(0, $xmlrpcerr['no_data'], $xmlrpcstr['no_data']); 1541 return $r; 1542 } 1543 // see if we got an HTTP 200 OK, else bomb 1544 // but only do this if we're using the HTTP protocol. 1545 if(ereg("^HTTP",$data)) 1546 { 1547 // Strip HTTP 1.1 100 Continue header if present 1548 while (ereg('^HTTP/1.1 1[0-9]{2}', $data)) 1549 { 1550 $pos = strpos($data, 'HTTP', 12); 1551 // server sent a Continue header without any (valid) content following... 1552 // give the client a chance to know it 1553 if (!$pos && !is_int($pos)) // works fine in php 3, 4 and 5 1554 break; 1555 $data = substr($data, $pos); 1556 } 1557 if (!ereg("^HTTP/[0-9\\.]+ 200 ", $data)) 1558 { 1559 $errstr= substr($data, 0, strpos($data, "\n")-1); 1560 error_log('HTTP error, got response: ' .$errstr); 1561 $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']. ' (' . $errstr . ')'); 1562 return $r; 1563 } 1564 } 1565 $parser = xml_parser_create($xmlrpc_defencoding); 1566 1567 // G. Giunta 2004/04/06 1568 // Clean up the accumulator, or it will grow indefinitely long 1569 // if making xmlrpc calls for a while 1570 $_xh=array(); 1571 $_xh[$parser]=array(); 1572 $_xh[$parser]['headers'] = array(); 1573 $_xh[$parser]['stack'] = array(); 1574 $_xh[$parser]['valuestack'] = array(); 1575 1576 // separate HTTP headers from data 1577 if (ereg("^HTTP", $data)) 1578 { 1579 // be tolerant to usage of \n instead of \r\n to separate headers and data 1580 // (even though it is not valid http) 1581 $pos = strpos($data,"\r\n\r\n"); 1582 if($pos || is_int($pos)) 1583 $bd = $pos+4; 1584 else 1585 { 1586 $pos = strpos($data,"\n\n"); 1587 if($pos || is_int($pos)) 1588 $bd = $pos+2; 1589 else 1590 { 1591 // No separation between response headers and body: fault? 1592 $bd = 0; 1593 } 1594 } 1595 // be tolerant to line endings, and extra empty lines 1596 $ar = split("\r?\n", trim(substr($data, 0, $pos))); 1597 while (list(,$line) = @each($ar)) 1598 { 1599 // take care of multi-line headers 1600 $arr = explode(':',$line); 1601 if(count($arr) > 1) 1602 { 1603 $header_name = trim($arr[0]); 1604 // TO DO: some headers (the ones that allow a CSV list of values) 1605 // do allow many values to be passed using multiple header lines. 1606 // We should add content to $_xh[$parser]['headers'][$header_name] 1607 // instead of replacing it for those... 1608 $_xh[$parser]['headers'][$header_name] = $arr[1]; 1609 for ($i = 2; $i < count($arr); $i++) 1610 { 1611 $_xh[$parser]['headers'][$header_name] .= ':'.$arr[$i]; 1612 } // while 1613 $_xh[$parser]['headers'][$header_name] = trim($_xh[$parser]['headers'][$header_name]); 1614 } else if (isset($header_name)) 1615 { 1616 $_xh[$parser]['headers'][$header_name] .= ' ' . trim($line); 1617 } 1618 } 1619 $data = substr($data, $bd); 1620 1621 if ($this->debug && count($_xh[$parser]['headers'])) 1622 { 1623 print '<PRE>'; 1624 //foreach ($_xh[$parser]['headers'] as $header) 1625 @reset($_xh[$parser]['headers']); 1626 while(list($header, $value) = @each($_xh[$parser]['headers'])) 1627 { 1628 print "HEADER: $header: $value\n"; 1629 } 1630 print "</PRE>\n"; 1631 } 1632 } 1633 1634 // be tolerant of extra whitespace in response body 1635 $data = trim($data); 1636 1637 // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts) 1638 // idea from Luca Mariano <luca.mariano@email.it> originally in PEARified version of the lib 1639 $bd = false; 1640 $pos = strpos($data, "</methodResponse>"); 1641 while ($pos || is_int($pos)) 1642 { 1643 $bd = $pos+17; 1644 $pos = strpos($data, "</methodResponse>", $bd); 1645 } 1646 if ($bd) 1647 $data = substr($data, 0, $bd); 1648 1649 //$_xh[$parser]['st']=''; 1650 //$_xh[$parser]['cm']=0; 1651 $_xh[$parser]['isf']=0; 1652 $_xh[$parser]['isf_reason']=0; 1653 $_xh[$parser]['ac']=''; 1654 //$_xh[$parser]['qt']=''; 1655 1656 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); 1657 // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell 1658 // the xml parser to give us back data in the expected charset 1659 xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $xmlrpc_internalencoding); 1660 1661 xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee'); 1662 xml_set_character_data_handler($parser, 'xmlrpc_cd'); 1663 xml_set_default_handler($parser, 'xmlrpc_dh'); 1664 //$xmlrpc_value=new xmlrpcval; 1665 1666 if (!xml_parse($parser, $data, sizeof($data))) 1667 { 1668 // thanks to Peter Kocks <peter.kocks@baygate.com> 1669 if((xml_get_current_line_number($parser)) == 1) 1670 { 1671 $errstr = 'XML error at line 1, check URL'; 1672 } 1673 else 1674 { 1675 $errstr = sprintf('XML error: %s at line %d', 1676 xml_error_string(xml_get_error_code($parser)), 1677 xml_get_current_line_number($parser)); 1678 } 1679 error_log($errstr); 1680 $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return'].' ('.$errstr.')'); 1681 xml_parser_free($parser); 1682 if ($this->debug) 1683 echo $errstr; 1684 $r->hdrs = $_xh[$parser]['headers']; 1685 return $r; 1686 } 1687 xml_parser_free($parser); 1688 1689 if ($_xh[$parser]['isf'] > 1) 1690 { 1691 if ($this->debug) 1692 { 1693 ///@todo echo something for user? 1694 } 1695 1696 $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], 1697 $xmlrpcstr['invalid_return'] . ' ' . $_xh[$parser]['isf_reason']); 1698 } 1699 //else if (strlen($_xh[$parser]['st'])==0) 1700 else if (!is_object($_xh[$parser]['value'])) 1701 { 1702 // then something odd has happened 1703 // and it's time to generate a client side error 1704 // indicating something odd went on 1705 $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'], 1706 $xmlrpcstr['invalid_return']); 1707 } 1708 else 1709 { 1710 1711 if ($this->debug) 1712 { 1713 //print "<PRE>---EVALING---[" . 1714 //strlen($_xh[$parser]['st']) . " chars]---\n" . 1715 //htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>"; 1716 print "<PRE>---PARSED---\n" ; 1717 var_dump($_xh[$parser]['value']); 1718 print "\n---END---</PRE>"; 1719 } 1720 1721 //$allOK=0; 1722 //@eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); 1723 //if (!$allOK) 1724 //{ 1725 // $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']); 1726 //} 1727 //else 1728 $v = $_xh[$parser]['value']; 1729 if ($_xh[$parser]['isf']) 1730 { 1731 $errno_v = $v->structmem('faultCode'); 1732 $errstr_v = $v->structmem('faultString'); 1733 $errno = $errno_v->scalarval(); 1734 1735 if ($errno == 0) 1736 { 1737 // FAULT returned, errno needs to reflect that 1738 $errno = -1; 1739 } 1740 1741 $r = new xmlrpcresp($v, $errno, $errstr_v->scalarval()); 1742 } 1743 else 1744 { 1745 $r=new xmlrpcresp($v); 1746 } 1747 } 1748 1749 $r->hdrs = $_xh[$parser]['headers']; 1750 return $r; 1751 } 1752 } 1753 1754 /** 1755 * @package evocore 1756 * @subpackage xmlrpc 1757 */ 1758 class xmlrpcval 1759 { 1760 var $me=array(); 1761 var $mytype=0; 1762 1763 /* 1764 * Type will default to string 1765 */ 1766 function xmlrpcval($val=-1, $type='') 1767 { 1768 global $xmlrpcTypes; 1769 $this->me=array(); 1770 $this->mytype=0; 1771 if ($val!=-1 || !is_int($val) || $type!='') 1772 { 1773 if ($type=='') 1774 { 1775 $type='string'; 1776 } 1777 if ($xmlrpcTypes[$type]==1) 1778 { 1779 $this->addScalar($val,$type); 1780 } 1781 elseif ($xmlrpcTypes[$type]==2) 1782 { 1783 $this->addArray($val); 1784 } 1785 elseif ($xmlrpcTypes[$type]==3) 1786 { 1787 $this->addStruct($val); 1788 } 1789 } 1790 } 1791 1792 function addScalar($val, $type='string') 1793 { 1794 global $xmlrpcTypes, $xmlrpcBoolean; 1795 1796 if ($this->mytype==1) 1797 { 1798 echo '<strong>xmlrpcval</strong>: scalar can have only one value<br />'; 1799 return 0; 1800 } 1801 $typeof=$xmlrpcTypes[$type]; 1802 if ($typeof!=1) 1803 { 1804 echo '<strong>xmlrpcval</strong>: not a scalar type ($typeof})<br />'; 1805 return 0; 1806 } 1807 1808 if ($type==$xmlrpcBoolean) 1809 { 1810 if (strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false'))) 1811 { 1812 $val=1; 1813 } 1814 else 1815 { 1816 $val=0; 1817 } 1818 } 1819 1820 if ($this->mytype==2) 1821 { 1822 // we're adding to an array here 1823 $ar=$this->me['array']; 1824 $ar[]=new xmlrpcval($val, $type); 1825 $this->me['array']=$ar; 1826 } 1827 else 1828 { 1829 // a scalar, so set the value and remember we're scalar 1830 $this->me[$type]=$val; 1831 $this->mytype=$typeof; 1832 } 1833 return 1; 1834 } 1835 1836 function addArray($vals) 1837 { 1838 global $xmlrpcTypes; 1839 if ($this->mytype!=0) 1840 { 1841 echo '<strong>xmlrpcval</strong>: already initialized as a [' . $this->kindOf() . ']<br />'; 1842 return 0; 1843 } 1844 1845 $this->mytype=$xmlrpcTypes['array']; 1846 $this->me['array']=$vals; 1847 return 1; 1848 } 1849 1850 function addStruct($vals) 1851 { 1852 global $xmlrpcTypes; 1853 if ($this->mytype!=0) 1854 { 1855 echo '<strong>xmlrpcval</strong>: already initialized as a [' . $this->kindOf() . ']<br />'; 1856 return 0; 1857 } 1858 $this->mytype=$xmlrpcTypes['struct']; 1859 $this->me['struct']=$vals; 1860 return 1; 1861 } 1862 1863 function dump($ar) 1864 { 1865 reset($ar); 1866 while ( list( $key, $val ) = each( $ar ) ) 1867 { 1868 echo "$key => $val<br />"; 1869 if ($key == 'array') 1870 { 1871 while ( list( $key2, $val2 ) = each( $val ) ) 1872 { 1873 echo "-- $key2 => $val2<br />"; 1874 } 1875 } 1876 } 1877 } 1878 1879 function kindOf() 1880 { 1881 switch($this->mytype) 1882 { 1883 case 3: 1884 return 'struct'; 1885 break; 1886 case 2: 1887 return 'array'; 1888 break; 1889 case 1: 1890 return 'scalar'; 1891 break; 1892 default: 1893 return 'undef'; 1894 } 1895 } 1896 1897 function serializedata($typ, $val) 1898 { 1899 $rs=''; 1900 global $xmlrpcTypes, $xmlrpcBase64, $xmlrpcString, 1901 $xmlrpcBoolean; 1902 switch(@$xmlrpcTypes[$typ]) 1903 { 1904 case 3: 1905 // struct 1906 $rs.="<struct>\n"; 1907 reset($val); 1908 while(list($key2, $val2)=each($val)) 1909 { 1910 $rs.="<member><name>$key2}</name>\n"; 1911 $rs.=$this->serializeval($val2); 1912 $rs.="</member>\n"; 1913 } 1914 $rs.='</struct>'; 1915 break; 1916 case 2: 1917 // array 1918 $rs.="<array>\n<data>\n"; 1919 for($i=0; $i<sizeof($val); $i++) 1920 { 1921 $rs.=$this->serializeval($val[$i]); 1922 } 1923 $rs.="</data>\n</array>"; 1924 break; 1925 case 1: 1926 switch ($typ) 1927 { 1928 case $xmlrpcBase64: 1929 $rs.="<$typ}>" . base64_encode($val) . "</$typ}>"; 1930 break; 1931 case $xmlrpcBoolean: 1932 $rs.="<$typ}>" . ($val ? '1' : '0') . "</$typ}>"; 1933 break; 1934 case $xmlrpcString: 1935 // G. Giunta 2005/2/13: do NOT use htmlentities, since 1936 // it will produce named html entities, which are invalid xml 1937 $rs.="<$typ}>" . xmlrpc_encode_entitites($val). "</$typ}>"; 1938 // $rs.="<${typ}>" . htmlentities($val). "</${typ}>"; 1939 break; 1940 default: 1941 $rs.="<$typ}>$val}</$typ}>"; 1942 } 1943 break; 1944 default: 1945 break; 1946 } 1947 return $rs; 1948 } 1949 1950 function serialize() 1951 { 1952 return $this->serializeval($this); 1953 } 1954 1955 function serializeval($o) 1956 { 1957 //global $xmlrpcTypes; 1958 $rs=''; 1959 $ar=$o->me; 1960 reset($ar); 1961 list($typ, $val) = each($ar); 1962 $rs.='<value>'; 1963 $rs.=$this->serializedata($typ, $val); 1964 $rs.="</value>\n"; 1965 return $rs; 1966 } 1967 1968 function structmem($m) 1969 { 1970 $nv=$this->me['struct'][$m]; 1971 return $nv; 1972 } 1973 1974 function structreset() 1975 { 1976 reset($this->me['struct']); 1977 } 1978 1979 function structeach() 1980 { 1981 return each($this->me['struct']); 1982 } 1983 1984 function getval() 1985 { 1986 // UNSTABLE 1987 global $xmlrpcBoolean, $xmlrpcBase64; 1988 reset($this->me); 1989 list($a,$b)=each($this->me); 1990 // contributed by I Sofer, 2001-03-24 1991 // add support for nested arrays to scalarval 1992 // i've created a new method here, so as to 1993 // preserve back compatibility 1994 1995 if (is_array($b)) 1996 { 1997 @reset($b); 1998 while(list($id,$cont) = @each($b)) 1999 { 2000 $b[$id] = $cont->scalarval(); 2001 } 2002 } 2003 2004 // add support for structures directly encoding php objects 2005 if (is_object($b)) 2006 { 2007 $t = get_object_vars($b); 2008 @reset($t); 2009 while(list($id,$cont) = @each($t)) 2010 { 2011 $t[$id] = $cont->scalarval(); 2012 } 2013 @reset($t); 2014 while(list($id,$cont) = @each($t)) 2015 { 2016 //eval('$b->'.$id.' = $cont;'); 2017 @$b->$id = $cont; 2018 } 2019 } 2020 // end contrib 2021 return $b; 2022 } 2023 2024 function scalarval() 2025 { 2026 //global $xmlrpcBoolean, $xmlrpcBase64; 2027 reset($this->me); 2028 list($a,$b)=each($this->me); 2029 return $b; 2030 } 2031 2032 function scalartyp() 2033 { 2034 global $xmlrpcI4, $xmlrpcInt; 2035 reset($this->me); 2036 list($a,$b)=each($this->me); 2037 if ($a==$xmlrpcI4) 2038 { 2039 $a=$xmlrpcInt; 2040 } 2041 return $a; 2042 } 2043 2044 function arraymem($m) 2045 { 2046 $nv=$this->me['array'][$m]; 2047 return $nv; 2048 } 2049 2050 function arraysize() 2051 { 2052 reset($this->me); 2053 list($a,$b)=each($this->me); 2054 return sizeof($b); 2055 } 2056 } 2057 2058 // date helpers 2059 function iso8601_encode($timet, $utc=0) 2060 { 2061 // return an ISO8601 encoded string 2062 // really, timezones ought to be supported 2063 // but the XML-RPC spec says: 2064 // 2065 // "Don't assume a timezone. It should be specified by the server in its 2066 // documentation what assumptions it makes about timezones." 2067 // 2068 // these routines always assume localtime unless 2069 // $utc is set to 1, in which case UTC is assumed 2070 // and an adjustment for locale is made when encoding 2071 if (!$utc) 2072 { 2073 $t=strftime("%Y%m%dT%H:%M:%S", $timet); 2074 } 2075 else 2076 { 2077 if (function_exists('gmstrftime')) 2078 { 2079 // gmstrftime doesn't exist in some versions 2080 // of PHP 2081 $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet); 2082 } 2083 else 2084 { 2085 $t=strftime("%Y%m%dT%H:%M:%S", $timet-date('Z')); 2086 } 2087 } 2088 return $t; 2089 } 2090 2091 function iso8601_decode($idate, $utc=0) 2092 { 2093 // return a timet in the localtime, or UTC 2094 $t=0; 2095 if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", $idate, $regs)) 2096 { 2097 if ($utc) 2098 { 2099 $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); 2100 } 2101 else 2102 { 2103 $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); 2104 } 2105 } 2106 return $t; 2107 } 2108 2109 /**************************************************************** 2110 * xmlrpc_decode takes a message in PHP xmlrpc object format and * 2111 * tranlates it into native PHP types. * 2112 * * 2113 * author: Dan Libby (dan@libby.com) * 2114 ****************************************************************/ 2115 /* 2116 * evocore: We add xmlrpc_decode_recurse because the default PHP implementation 2117 * of xmlrpc_decode won't recurse! Bleh! 2118 * update: XML-RPC for PHP now copes with this, but we keep a stub for backward compatibility 2119 */ 2120 function xmlrpc_decode_recurse($xmlrpc_val) 2121 { 2122 return php_xmlrpc_decode($xmlrpc_val); 2123 } 2124 2125 function php_xmlrpc_decode($xmlrpc_val) 2126 { 2127 $kind = $xmlrpc_val->kindOf(); 2128 2129 if($kind == 'scalar') 2130 { 2131 return $xmlrpc_val->scalarval(); 2132 } 2133 elseif($kind == 'array') 2134 { 2135 $size = $xmlrpc_val->arraysize(); 2136 $arr = array(); 2137 2138 for($i = 0; $i < $size; $i++) 2139 { 2140 $arr[] = php_xmlrpc_decode($xmlrpc_val->arraymem($i)); 2141 } 2142 return $arr; 2143 } 2144 elseif($kind == 'struct') 2145 { 2146 $xmlrpc_val->structreset(); 2147 $arr = array(); 2148 2149 while(list($key,$value)=$xmlrpc_val->structeach()) 2150 { 2151 $arr[$key] = php_xmlrpc_decode($value); 2152 // echo $key, '=>', $arr[$key], '<br />'; 2153 } 2154 return $arr; 2155 } 2156 } 2157 2158 if(function_exists('xmlrpc_decode')) 2159 { 2160 define('XMLRPC_EPI_ENABLED','1'); 2161 } 2162 else 2163 { 2164 define('XMLRPC_EPI_ENABLED','0'); 2165 function xmlrpc_decode($xmlrpc_val) 2166 { 2167 $kind = $xmlrpc_val->kindOf(); 2168 2169 if($kind == 'scalar') 2170 { 2171 return $xmlrpc_val->scalarval(); 2172 } 2173 elseif($kind == 'array') 2174 { 2175 $size = $xmlrpc_val->arraysize(); 2176 $arr = array(); 2177 2178 for($i = 0; $i < $size; $i++) 2179 { 2180 $arr[]=xmlrpc_decode($xmlrpc_val->arraymem($i)); 2181 } 2182 return $arr; 2183 } 2184 elseif($kind == 'struct') 2185 { 2186 $xmlrpc_val->structreset(); 2187 $arr = array(); 2188 2189 while(list($key,$value)=$xmlrpc_val->structeach()) 2190 { 2191 $arr[$key] = xmlrpc_decode($value); 2192 } 2193 return $arr; 2194 } 2195 } 2196 } 2197 2198 /**************************************************************** 2199 * xmlrpc_encode takes native php types and encodes them into * 2200 * xmlrpc PHP object format. * 2201 * BUG: All sequential arrays are turned into structs. I don't * 2202 * know of a good way to determine if an array is sequential * 2203 * only. * 2204 * * 2205 * feature creep -- could support more types via optional type * 2206 * argument. * 2207 * * 2208 * author: Dan Libby (dan@libby.com) * 2209 ****************************************************************/ 2210 function php_xmlrpc_encode($php_val) 2211 { 2212 global $xmlrpcInt; 2213 global $xmlrpcDouble; 2214 global $xmlrpcString; 2215 global $xmlrpcArray; 2216 global $xmlrpcStruct; 2217 global $xmlrpcBoolean; 2218 2219 $type = gettype($php_val); 2220 $xmlrpc_val = new xmlrpcval; 2221 2222 switch($type) 2223 { 2224 case 'array': 2225 case 'object': 2226 $arr = array(); 2227 while (list($k,$v) = each($php_val)) 2228 { 2229 $arr[$k] = php_xmlrpc_encode($v); 2230 } 2231 $xmlrpc_val->addStruct($arr); 2232 break; 2233 case 'integer': 2234 $xmlrpc_val->addScalar($php_val, $xmlrpcInt); 2235 break; 2236 case 'double': 2237 $xmlrpc_val->addScalar($php_val, $xmlrpcDouble); 2238 break; 2239 case 'string': 2240 $xmlrpc_val->addScalar($php_val, $xmlrpcString); 2241 break; 2242 // <G_Giunta_2001-02-29> 2243 // Add support for encoding/decoding of booleans, since they are supported in PHP 2244 case 'boolean': 2245 $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean); 2246 break; 2247 // </G_Giunta_2001-02-29> 2248 // catch "resource", "NULL", "user function", "unknown type" 2249 //case 'unknown type': 2250 default: 2251 // giancarlo pinerolo <ping@alt.it> 2252 // it has to return 2253 // an empty object in case (which is already 2254 // at this point), not a boolean. 2255 break; 2256 } 2257 return $xmlrpc_val; 2258 } 2259 2260 if(XMLRPC_EPI_ENABLED == '0') 2261 { 2262 function xmlrpc_encode($php_val) 2263 { 2264 global $xmlrpcInt; 2265 global $xmlrpcDouble; 2266 global $xmlrpcString; 2267 global $xmlrpcArray; 2268 global $xmlrpcStruct; 2269 global $xmlrpcBoolean; 2270 2271 $type = gettype($php_val); 2272 $xmlrpc_val = new xmlrpcval; 2273 2274 switch($type) 2275 { 2276 case 'array': 2277 case 'object': 2278 $arr = array(); 2279 while (list($k,$v) = each($php_val)) 2280 { 2281 $arr[$k] = xmlrpc_encode($v); 2282 } 2283 $xmlrpc_val->addStruct($arr); 2284 break; 2285 case 'integer': 2286 $xmlrpc_val->addScalar($php_val, $xmlrpcInt); 2287 break; 2288 case 'double': 2289 $xmlrpc_val->addScalar($php_val, $xmlrpcDouble); 2290 break; 2291 case 'string': 2292 $xmlrpc_val->addScalar($php_val, $xmlrpcString); 2293 break; 2294 // <G_Giunta_2001-02-29> 2295 // Add support for encoding/decoding of booleans, since they are supported in PHP 2296 case 'boolean': 2297 $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean); 2298 break; 2299 // </G_Giunta_2001-02-29> 2300 //case 'unknown type': 2301 default: 2302 // giancarlo pinerolo <ping@alt.it> 2303 // it has to return 2304 // an empty object in case (which is already 2305 // at this point), not a boolean. 2306 break; 2307 } 2308 return $xmlrpc_val; 2309 } 2310 } 2311 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |