[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 <?php 2 // by Edd Dumbill (C) 1999-2001 3 // <edd@usefulinc.com> 4 // xmlrpc.inc,v 1.18 2001/07/06 18:23:57 edmundd 5 6 // License is granted to use or modify this software ("XML-RPC for PHP") 7 // for commercial or non-commercial use provided the copyright of the author 8 // is preserved in any distributed or derivative work. 9 10 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR 11 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 12 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 13 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 14 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 15 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 16 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 17 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 18 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 19 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 21 /* $Id: xml_functions.inc.php 20496 2006-03-08 19:40:11Z ralfbecker $ */ 22 23 if (!function_exists('xml_parser_create')) 24 { 25 // Win 32 fix. From: "Leo West" <lwest@imaginet.fr> 26 if($WINDIR) 27 { 28 dl('php3_xml.dll'); 29 } 30 else 31 { 32 dl('xml.so'); 33 } 34 } 35 36 $GLOBALS['xmlrpc_valid_parents'] = array( 37 'BOOLEAN' => array('VALUE'), 38 'I4' => array('VALUE'), 39 'INT' => array('VALUE'), 40 'STRING' => array('VALUE'), 41 'DOUBLE' => array('VALUE'), 42 'DATETIME.ISO8601' => array('VALUE'), 43 'BASE64' => array('VALUE'), 44 'ARRAY' => array('VALUE'), 45 'STRUCT' => array('VALUE'), 46 'PARAM' => array('PARAMS'), 47 'METHODNAME' => array('METHODCALL'), 48 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), 49 'MEMBER' => array('STRUCT'), 50 'NAME' => array('MEMBER'), 51 'DATA' => array('ARRAY'), 52 'FAULT' => array('METHODRESPONSE'), 53 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), 54 ); 55 56 define('xmlrpcI4','i4'); 57 define('xmlrpcInt','int'); 58 define('xmlrpcBoolean','boolean'); 59 define('xmlrpcDouble','double'); 60 define('xmlrpcString','string'); 61 define('xmlrpcDateTime','dateTime.iso8601'); 62 define('xmlrpcBase64','base64'); 63 define('xmlrpcArray','array'); 64 define('xmlrpcStruct','struct'); 65 66 $GLOBALS['xmlrpcTypes'] = array( 67 xmlrpcI4 => 1, 68 xmlrpcInt => 1, 69 xmlrpcBoolean => 1, 70 xmlrpcString => 1, 71 xmlrpcDouble => 1, 72 xmlrpcDateTime => 1, 73 xmlrpcBase64 => 1, 74 xmlrpcArray => 2, 75 xmlrpcStruct => 3 76 ); 77 78 $GLOBALS['xmlEntities']=array( 79 'amp' => '&', 80 'quot' => '"', 81 'lt' => '<', 82 'gt' => '>', 83 'apos' => "'" 84 ); 85 86 $GLOBALS['xmlrpcerr']['unknown_method']=1; 87 $GLOBALS['xmlrpcstr']['unknown_method']='Unknown method'; 88 $GLOBALS['xmlrpcerr']['invalid_return']=2; 89 $GLOBALS['xmlrpcstr']['invalid_return']='Invalid return payload: enable debugging to examine incoming payload'; 90 $GLOBALS['xmlrpcerr']['incorrect_params']=3; 91 $GLOBALS['xmlrpcstr']['incorrect_params']='Incorrect parameters passed to method'; 92 $GLOBALS['xmlrpcerr']['introspect_unknown']=4; 93 $GLOBALS['xmlrpcstr']['introspect_unknown']="Can't introspect: method unknown"; 94 $GLOBALS['xmlrpcerr']['http_error']=5; 95 $GLOBALS['xmlrpcstr']['http_error']="Didn't receive 200 OK from remote server."; 96 $GLOBALS['xmlrpcerr']['no_data']=6; 97 $GLOBALS['xmlrpcstr']['no_data']='No data received from server.'; 98 $GLOBALS['xmlrpcerr']['no_ssl']=7; 99 $GLOBALS['xmlrpcstr']['no_ssl']='No SSL support compiled in.'; 100 $GLOBALS['xmlrpcerr']['curl_fail']=8; 101 $GLOBALS['xmlrpcstr']['curl_fail']='CURL error'; 102 $GLOBALS['xmlrpcerr']['multicall_notstruct'] = 9; 103 $GLOBALS['xmlrpcstr']['multicall_notstruct'] = 'system.multicall expected struct'; 104 $GLOBALS['xmlrpcerr']['multicall_nomethod'] = 10; 105 $GLOBALS['xmlrpcstr']['multicall_nomethod'] = 'missing methodName'; 106 $GLOBALS['xmlrpcerr']['multicall_notstring'] = 11; 107 $GLOBALS['xmlrpcstr']['multicall_notstring'] = 'methodName is not a string'; 108 $GLOBALS['xmlrpcerr']['multicall_recursion'] = 12; 109 $GLOBALS['xmlrpcstr']['multicall_recursion'] = 'recursive system.multicall forbidden'; 110 $GLOBALS['xmlrpcerr']['multicall_noparams'] = 13; 111 $GLOBALS['xmlrpcstr']['multicall_noparams'] = 'missing params'; 112 $GLOBALS['xmlrpcerr']['multicall_notarray'] = 14; 113 $GLOBALS['xmlrpcstr']['multicall_notarray'] = 'params is not an array'; 114 115 $GLOBALS['xmlrpcerr']['invalid_request']=15; 116 $GLOBALS['xmlrpcstr']['invalid_request']='Invalid request payload'; 117 $GLOBALS['xmlrpcerr']['no_curl']=16; 118 $GLOBALS['xmlrpcstr']['no_curl']='No CURL support compiled in.'; 119 $GLOBALS['xmlrpcerr']['server_error']=17; 120 $GLOBALS['xmlrpcstr']['server_error']='Internal server error'; 121 122 $GLOBALS['xmlrpcerr']['no_access'] = 18; 123 $GLOBALS['xmlrpcstr']['no_access'] = 'Access denied'; 124 $GLOBALS['xmlrpcerr']['not_existent'] = 19; 125 $GLOBALS['xmlrpcstr']['not_existent'] = 'Entry does not (longer) exist!'; 126 127 $GLOBALS['xmlrpcerr']['cannot_decompress']=103; 128 $GLOBALS['xmlrpcstr']['cannot_decompress']='Received from server compressed HTTP and cannot decompress'; 129 $GLOBALS['xmlrpcerr']['decompress_fail']=104; 130 $GLOBALS['xmlrpcstr']['decompress_fail']='Received from server invalid compressed HTTP'; 131 $GLOBALS['xmlrpcerr']['dechunk_fail']=105; 132 $GLOBALS['xmlrpcstr']['dechunk_fail']='Received from server invalid chunked HTTP'; 133 $GLOBALS['xmlrpcerr']['server_cannot_decompress']=106; 134 $GLOBALS['xmlrpcstr']['server_cannot_decompress']='Received from client compressed HTTP request and cannot decompress'; 135 $GLOBALS['xmlrpcerr']['server_decompress_fail']=107; 136 $GLOBALS['xmlrpcstr']['server_decompress_fail']='Received from client invalid compressed HTTP request'; 137 138 $GLOBALS['xmlrpc_defencoding'] = 'UTF-8'; 139 $GLOBALS['xmlrpc_internalencoding']='ISO-8859-1'; 140 141 $GLOBALS['xmlrpcName'] = 'XML-RPC for PHP'; 142 $GLOBALS['xmlrpcVersion'] = '2.0'; 143 144 // let user errors start at 800 145 $GLOBALS['xmlrpcerruser'] = 800; 146 // let XML parse errors start at 100 147 $GLOBALS['xmlrpcerrxml'] = 100; 148 149 // formulate backslashes for escaping regexp 150 $GLOBALS['xmlrpc_backslash'] = chr(92) . chr(92); 151 152 /*! 153 @function xmlrpcfault 154 @abstract Error reporting for XML-RPC 155 @discussion Author: jengo <br> 156 Returns XML-RPC fault and stops this execution of the application. <br> 157 Syntax: void xmlrpcfault(string) <br> 158 Example1: xmlrpcfault('Session could not be verifed'); <br> 159 @param $string Error message to be returned. 160 */ 161 function xmlrpcfault($string) 162 { 163 $r = CreateObject('phpgwapi.xmlrpcresp', 164 CreateObject('phpgwapi.xmlrpcval'), 165 $GLOBALS['xmlrpcerr']['unknown_method'], 166 $string 167 ); 168 $payload = '<?xml version="1.0"?>' . "\n" . $r->serialize(); 169 Header('Content-type: text/xml'); 170 Header('Content-length: ' . strlen($payload)); 171 print $payload; 172 $GLOBALS['egw']->common->phpgw_exit(False); 173 } 174 175 // used to store state during parsing 176 // quick explanation of components: 177 // ac - used to accumulate values 178 // isf - used to indicate a fault 179 // lv - used to indicate "looking for a value": implements 180 // the logic to allow values with no types to be strings 181 // params - used to store parameters in method calls 182 // method - used to store method name 183 // stack - array with genealogy of xml elements names: 184 // used to validate nesting of xmlrpc elements 185 $GLOBALS['_xh'] = null; 186 187 /** 188 * To help correct communication of non-ascii chars inside strings, regardless 189 * of the charset used when sending requests, parsing them, sending responses 190 * and parsing responses, convert all non-ascii chars present in the message 191 * into their equivalent 'charset entity'. Charset entities enumerated this way 192 * are independent of the charset encoding used to transmit them, and all XML 193 * parsers are bound to understand them. 194 */ 195 function xmlrpc_encode_entitites($data) 196 { 197 $length = strlen($data); 198 $escapeddata = ""; 199 for($position = 0; $position < $length; $position++) 200 { 201 $character = substr($data, $position, 1); 202 $code = Ord($character); 203 switch($code) 204 { 205 case 34: 206 $character = """; 207 break; 208 case 38: 209 $character = "&"; 210 break; 211 case 39: 212 $character = "'"; 213 break; 214 case 60: 215 $character = "<"; 216 break; 217 case 62: 218 $character = ">"; 219 break; 220 default: 221 if($code < 32 || $code > 159) 222 { 223 $character = ("&#".strval($code).";"); 224 } 225 break; 226 } 227 $escapeddata .= $character; 228 } 229 return $escapeddata; 230 } 231 232 function xmlrpc_entity_decode($string) 233 { 234 $top = split('&', $string); 235 $op = ''; 236 $i = 0; 237 while($i<sizeof($top)) 238 { 239 if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) 240 { 241 $op .= ereg_replace("^[#a-zA-Z0-9]+;", 242 xmlrpc_lookup_entity($regs[1]), $top[$i]); 243 } 244 else 245 { 246 if ($i == 0) 247 { 248 $op = $top[$i]; 249 } 250 else 251 { 252 $op .= '&' . $top[$i]; 253 } 254 } 255 $i++; 256 } 257 return $op; 258 } 259 260 function xmlrpc_lookup_entity($ent) 261 { 262 if (isset($GLOBALS['xmlEntities'][strtolower($ent)])) 263 { 264 return $GLOBALS['xmlEntities'][strtolower($ent)]; 265 } 266 if (ereg("^#([0-9]+)$", $ent, $regs)) 267 { 268 return chr($regs[1]); 269 } 270 return '?'; 271 } 272 273 function xmlrpc_se($parser, $name, $attrs) 274 { 275 // if invalid xmlrpc already detected, skip all processing 276 if ($GLOBALS['_xh'][$parser]['isf'] < 2) 277 { 278 // check for correct element nesting 279 // top level element can only be of 2 types 280 if (count($GLOBALS['_xh'][$parser]['stack']) == 0) 281 { 282 if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') 283 { 284 $GLOBALS['_xh'][$parser]['isf'] = 2; 285 $GLOBALS['_xh'][$parser]['isf_reason'] = 'missing top level xmlrpc element'; 286 return; 287 } 288 } 289 else 290 { 291 // not top level element: see if parent is OK 292 if (!in_array($GLOBALS['_xh'][$parser]['stack'][0], $GLOBALS['xmlrpc_valid_parents'][$name])) 293 { 294 $GLOBALS['_xh'][$parser]['isf'] = 2; 295 $GLOBALS['_xh'][$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$GLOBALS['_xh'][$parser]['stack'][0]}"; 296 return; 297 } 298 } 299 300 switch($name) 301 { 302 case 'STRUCT': 303 case 'ARRAY': 304 // create an empty array to hold child values, and push it onto appropriate stack 305 $cur_val = array(); 306 $cur_val['values'] = array(); 307 $cur_val['type'] = $name; 308 @array_unshift($GLOBALS['_xh'][$parser]['valuestack'], $cur_val); 309 break; 310 case 'DATA': 311 case 'METHODCALL': 312 case 'METHODRESPONSE': 313 case 'PARAMS': 314 // valid elements that add little to processing 315 break; 316 case 'METHODNAME': 317 case 'NAME': 318 $GLOBALS['_xh'][$parser]['ac']=''; 319 break; 320 case 'FAULT': 321 $GLOBALS['_xh'][$parser]['isf']=1; 322 break; 323 case 'VALUE': 324 $GLOBALS['_xh'][$parser]['vt']='value'; // indicator: no value found yet 325 $GLOBALS['_xh'][$parser]['ac']=''; 326 $GLOBALS['_xh'][$parser]['lv']=1; 327 break; 328 case 'I4': 329 case 'INT': 330 case 'STRING': 331 case 'BOOLEAN': 332 case 'DOUBLE': 333 case 'DATETIME.ISO8601': 334 case 'BASE64': 335 if ($GLOBALS['_xh'][$parser]['vt']!='value') 336 { 337 //two data elements inside a value: an error occurred! 338 $GLOBALS['_xh'][$parser]['isf'] = 2; 339 $GLOBALS['_xh'][$parser]['isf_reason'] = "$name element following a {$GLOBALS['_xh'][$parser]['vt']} element inside a single value"; 340 return; 341 } 342 343 $GLOBALS['_xh'][$parser]['ac']=''; // reset the accumulator 344 break; 345 case 'MEMBER': 346 $GLOBALS['_xh'][$parser]['valuestack'][0]['name']=''; // set member name to null, in case we do not find in the xml later on 347 //$GLOBALS['_xh'][$parser]['ac']=''; 348 // Drop trough intentionally 349 case 'PARAM': 350 // clear value, so we can check later if no value will passed for this param/member 351 $GLOBALS['_xh'][$parser]['value']=null; 352 break; 353 default: 354 /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!! 355 $GLOBALS['_xh'][$parser]['isf'] = 2; 356 $GLOBALS['_xh'][$parser]['isf_reason'] = "found not-xmlrpc xml element $name"; 357 break; 358 } 359 360 // Save current element name to stack, to validate nesting 361 @array_unshift($GLOBALS['_xh'][$parser]['stack'], $name); 362 363 if($name!='VALUE') 364 { 365 $GLOBALS['_xh'][$parser]['lv']=0; 366 } 367 } 368 } 369 370 function xmlrpc_ee($parser, $name) 371 { 372 if ($GLOBALS['_xh'][$parser]['isf'] < 2) 373 { 374 // push this element name from stack 375 // NB: if XML validates, correct opening/closing is guaranteed and 376 // we do not have to check for $name == $curr_elem. 377 // we also checked for proper nesting at start of elements... 378 $curr_elem = array_shift($GLOBALS['_xh'][$parser]['stack']); 379 380 switch($name) 381 { 382 case 'STRUCT': 383 case 'ARRAY': 384 // fetch out of stack array of values, and promote it to current value 385 $curr_val = array_shift($GLOBALS['_xh'][$parser]['valuestack']); 386 $GLOBALS['_xh'][$parser]['value'] = $curr_val['values']; 387 388 $GLOBALS['_xh'][$parser]['vt']=strtolower($name); 389 break; 390 case 'NAME': 391 $GLOBALS['_xh'][$parser]['valuestack'][0]['name'] = $GLOBALS['_xh'][$parser]['ac']; 392 break; 393 case 'BOOLEAN': 394 case 'I4': 395 case 'INT': 396 case 'STRING': 397 case 'DOUBLE': 398 case 'DATETIME.ISO8601': 399 case 'BASE64': 400 $GLOBALS['_xh'][$parser]['vt']=strtolower($name); 401 if ($name=='STRING') 402 { 403 $GLOBALS['_xh'][$parser]['value']=$GLOBALS['_xh'][$parser]['ac']; 404 } 405 elseif ($name=='DATETIME.ISO8601') 406 { 407 $GLOBALS['_xh'][$parser]['vt'] = xmlrpcDateTime; 408 $GLOBALS['_xh'][$parser]['value']=$GLOBALS['_xh'][$parser]['ac']; 409 } 410 elseif ($name=='BASE64') 411 { 412 ///@todo check for failure of base64 decoding / catch warnings 413 $GLOBALS['_xh'][$parser]['value'] = base64_decode($GLOBALS['_xh'][$parser]['ac']); 414 } 415 elseif ($name=='BOOLEAN') 416 { 417 // special case here: we translate boolean 1 or 0 into PHP 418 // constants true or false 419 // NB: this simple checks helps a lot sanitizing input, ie no 420 // security problems around here 421 if ($GLOBALS['_xh'][$parser]['ac']=='1') 422 { 423 $GLOBALS['_xh'][$parser]['value']=true; 424 } 425 else 426 { 427 // log if receiveing something strange, even though we set the value to false anyway 428 if ($GLOBALS['_xh'][$parser]['ac']!='0') 429 error_log('XML-RPC: invalid value received in BOOLEAN: '.$GLOBALS['_xh'][$parser]['ac']); 430 $GLOBALS['_xh'][$parser]['value']=false; 431 } 432 } 433 elseif ($name=='DOUBLE') 434 { 435 // we have a DOUBLE 436 // we must check that only 0123456789-.<space> are characters here 437 if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$", $GLOBALS['_xh'][$parser]['ac'])) 438 { 439 // TODO: find a better way of throwing an error 440 // than this! 441 error_log('XML-RPC: non numeric value received in DOUBLE: '.$GLOBALS['_xh'][$parser]['ac']); 442 $GLOBALS['_xh'][$parser]['value']='ERROR_NON_NUMERIC_FOUND'; 443 } 444 else 445 { 446 // it's ok, add it on 447 $GLOBALS['_xh'][$parser]['value']=(double)$GLOBALS['_xh'][$parser]['ac']; 448 } 449 } 450 else 451 { 452 // we have an I4/INT 453 // we must check that only 0123456789-<space> are characters here 454 if (!ereg("^[+-]?[0123456789 \\t]+$", $GLOBALS['_xh'][$parser]['ac'])) 455 { 456 // TODO: find a better way of throwing an error 457 // than this! 458 error_log('XML-RPC: non numeric value received in INT: '.$GLOBALS['_xh'][$parser]['ac']); 459 $GLOBALS['_xh'][$parser]['value']='ERROR_NON_NUMERIC_FOUND'; 460 } 461 else 462 { 463 // it's ok, add it on 464 $GLOBALS['_xh'][$parser]['value'] = (int)$GLOBALS['_xh'][$parser]['ac']; 465 } 466 } 467 $GLOBALS['_xh'][$parser]['ac']=''; // is this necessary? 468 $GLOBALS['_xh'][$parser]['lv']=3; // indicate we've found a value 469 break; 470 case 'VALUE': 471 // This if() detects if no scalar was inside <VALUE></VALUE> 472 if ($GLOBALS['_xh'][$parser]['vt'] == 'value') 473 { 474 $GLOBALS['_xh'][$parser]['value'] = $GLOBALS['_xh'][$parser]['ac']; 475 $GLOBALS['_xh'][$parser]['vt'] = xmlrpcString; 476 } 477 478 // build the xmlrpc val out of the data received, and substitute it 479 $temp =& CreateObject('phpgwapi.xmlrpcval',$GLOBALS['_xh'][$parser]['value'], $GLOBALS['_xh'][$parser]['vt']); 480 // check if we are inside an array or struct: 481 // if value just built is inside an array, let's move it into array on the stack 482 if (count($GLOBALS['_xh'][$parser]['valuestack']) && $GLOBALS['_xh'][$parser]['valuestack'][0]['type']=='ARRAY') 483 { 484 $GLOBALS['_xh'][$parser]['valuestack'][0]['values'][] = $temp; 485 } 486 else 487 { 488 $GLOBALS['_xh'][$parser]['value'] = $temp; 489 } 490 break; 491 case 'MEMBER': 492 $GLOBALS['_xh'][$parser]['ac']=''; // is this necessary? 493 // add to array in the stack the last element built, 494 // unless no VALUE was found 495 if ($GLOBALS['_xh'][$parser]['value']) 496 $GLOBALS['_xh'][$parser]['valuestack'][0]['values'][$GLOBALS['_xh'][$parser]['valuestack'][0]['name']] = $GLOBALS['_xh'][$parser]['value']; 497 else 498 error_log('XML-RPC: missing VALUE inside STRUCT in received xml'); 499 break; 500 case 'DATA': 501 $GLOBALS['_xh'][$parser]['ac']=''; // is this necessary? 502 break; 503 case 'PARAM': 504 // add to array of params the current value, 505 // unless no VALUE was found 506 if ($GLOBALS['_xh'][$parser]['value']) 507 $GLOBALS['_xh'][$parser]['params'][]=$GLOBALS['_xh'][$parser]['value']; 508 else 509 error_log('XML-RPC: missing VALUE inside PARAM in received xml'); 510 break; 511 case 'METHODNAME': 512 $GLOBALS['_xh'][$parser]['method']=ereg_replace("^[\n\r\t ]+", '', $GLOBALS['_xh'][$parser]['ac']); 513 break; 514 case 'PARAMS': 515 case 'FAULT': 516 case 'METHODCALL': 517 case 'METHORESPONSE': 518 break; 519 default: 520 // End of INVALID ELEMENT! 521 // shall we add an assert here for unreachable code??? 522 break; 523 } 524 } 525 } 526 527 function xmlrpc_cd($parser, $data) 528 { 529 //if(ereg("^[\n\r \t]+$", $data)) return; 530 // print "adding [${data}]\n"; 531 532 // skip processing if xml fault already detected 533 if ($GLOBALS['_xh'][$parser]['isf'] < 2) 534 { 535 if($GLOBALS['_xh'][$parser]['lv']!=3) 536 { 537 // "lookforvalue==3" means that we've found an entire value 538 // and should discard any further character data 539 if($GLOBALS['_xh'][$parser]['lv']==1) 540 { 541 // if we've found text and we're just in a <value> then 542 // say we've found a value 543 $GLOBALS['_xh'][$parser]['lv']=2; 544 } 545 if(!@isset($GLOBALS['_xh'][$parser]['ac'])) 546 { 547 $GLOBALS['_xh'][$parser]['ac'] = ''; 548 } 549 $GLOBALS['_xh'][$parser]['ac'].=$data; 550 } 551 } 552 } 553 554 function xmlrpc_dh($parser, $data) 555 { 556 // skip processing if xml fault already detected 557 if ($GLOBALS['_xh'][$parser]['isf'] < 2) 558 { 559 if(substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') 560 { 561 if($GLOBALS['_xh'][$parser]['lv']==1) 562 { 563 $GLOBALS['_xh'][$parser]['lv']=2; 564 } 565 $GLOBALS['_xh'][$parser]['ac'].=$data; 566 } 567 } 568 } 569 570 // date helpers 571 function iso8601_encode($timet, $utc=0) 572 { 573 // return an ISO8601 encoded string 574 // really, timezones ought to be supported 575 // but the XML-RPC spec says: 576 // 577 // "Don't assume a timezone. It should be specified by the server in its 578 // documentation what assumptions it makes about timezones." 579 // 580 // these routines always assume localtime unless 581 // $utc is set to 1, in which case UTC is assumed 582 // and an adjustment for locale is made when encoding 583 if (!$utc) 584 { 585 $t=strftime("%Y%m%dT%H:%M:%S", $timet); 586 } 587 else 588 { 589 if(function_exists('gmstrftime')) 590 { 591 // gmstrftime doesn't exist in some versions 592 // of PHP 593 $t = gmstrftime("%Y%m%dT%H:%M:%S", $timet); 594 } 595 else 596 { 597 $t = strftime('%Y%m%dT%H:%M:%S', $timet-date('Z')); 598 } 599 } 600 return $t; 601 } 602 603 function iso8601_decode($idate, $utc=0) 604 { 605 // return a time in the localtime, or UTC 606 $t = 0; 607 if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})",$idate, $regs)) 608 { 609 if ($utc) 610 { 611 $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); 612 } 613 else 614 { 615 $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); 616 } 617 } 618 return $t; 619 } 620 621 /**************************************************************** 622 * xmlrpc_decode takes a message in PHP xmlrpc object format and * 623 * tranlates it into native PHP types. * 624 * * 625 * author: Dan Libby (dan@libby.com) * 626 ****************************************************************/ 627 function phpgw_xmlrpc_decode($xmlrpc_val) 628 { 629 $kind = @$xmlrpc_val->kindOf(); 630 631 if($kind == 'scalar') 632 { 633 return $xmlrpc_val->scalarval(); 634 } 635 elseif($kind == 'array') 636 { 637 $size = $xmlrpc_val->arraysize(); 638 $arr = array(); 639 640 for($i = 0; $i < $size; $i++) 641 { 642 $arr[] = phpgw_xmlrpc_decode($xmlrpc_val->arraymem($i)); 643 } 644 return $arr; 645 } 646 elseif($kind == 'struct') 647 { 648 $xmlrpc_val->structreset(); 649 $arr = array(); 650 651 while(list($key,$value)=$xmlrpc_val->structeach()) 652 { 653 $arr[$key] = phpgw_xmlrpc_decode($value); 654 } 655 return $arr; 656 } 657 } 658 659 /**************************************************************** 660 * xmlrpc_encode takes native php types and encodes them into * 661 * xmlrpc PHP object format. * 662 * BUG: All sequential arrays are turned into structs. I don't * 663 * know of a good way to determine if an array is sequential * 664 * only. * 665 * * 666 * feature creep -- could support more types via optional type * 667 * argument. * 668 * * 669 * author: Dan Libby (dan@libby.com) * 670 ****************************************************************/ 671 function phpgw_xmlrpc_encode($php_val) 672 { 673 $type = gettype($php_val); 674 $xmlrpc_val = CreateObject('phpgwapi.xmlrpcval'); 675 676 switch($type) 677 { 678 case 'array': 679 case 'object': 680 $arr = array(); 681 while(list($k,$v) = each($php_val)) 682 { 683 $arr[$k] = phpgw_xmlrpc_encode($v); 684 } 685 $xmlrpc_val->addStruct($arr); 686 break; 687 case 'integer': 688 $xmlrpc_val->addScalar($php_val, xmlrpcInt); 689 break; 690 case 'double': 691 $xmlrpc_val->addScalar($php_val, xmlrpcDouble); 692 break; 693 case 'string': 694 $xmlrpc_val->addScalar($php_val, xmlrpcString); 695 break; 696 // <G_Giunta_2001-02-29> 697 // Add support for encoding/decoding of booleans, since they are supported in PHP 698 case 'boolean': 699 $xmlrpc_val->addScalar($php_val, xmlrpcBoolean); 700 break; 701 // </G_Giunta_2001-02-29> 702 case 'unknown type': 703 default: 704 $xmlrpc_val = False; 705 break; 706 } 707 return $xmlrpc_val; 708 } 709 710 /* The following functions are the system functions for login, logout, etc. 711 * They are added to the server map at the end of this file. 712 */ 713 714 $GLOBALS['_xmlrpcs_listMethods_sig'] = array(array(xmlrpcArray, xmlrpcString), array(xmlrpcArray)); 715 $GLOBALS['_xmlrpcs_listMethods_doc'] = 'This method lists all the methods that the XML-RPC server knows how to dispatch'; 716 function _xmlrpcs_listMethods($server, $m) 717 { 718 $v = CreateObject('phpgwapi.xmlrpcval'); 719 $dmap = $server->dmap; 720 $outAr = array(); 721 for(reset($dmap); list($key, $val) = each($dmap); ) 722 { 723 $outAr[] = CreateObject('phpgwapi.xmlrpcval',$key, 'string'); 724 } 725 $dmap = $GLOBALS['_xmlrpcs_dmap']; 726 for(reset($dmap); list($key, $val) = each($dmap); ) 727 { 728 $outAr[] = CreateObject('phpgwapi.xmlrpcval',$key, 'string'); 729 } 730 $v->addArray($outAr); 731 return CreateObject('phpgwapi.xmlrpcresp',$v); 732 } 733 734 $GLOBALS['_xmlrpcs_methodSignature_sig']=array(array(xmlrpcArray, xmlrpcString)); 735 $GLOBALS['_xmlrpcs_methodSignature_doc']='Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)'; 736 function _xmlrpcs_methodSignature($server, $m) 737 { 738 $methName = $m->getParam(0); 739 $methName = $methName->scalarval(); 740 if (ereg("^system\.", $methName)) 741 { 742 $dmap = $GLOBALS['_xmlrpcs_dmap']; 743 $sysCall = 1; 744 } 745 else 746 { 747 $dmap = $server->dmap; 748 $sysCall = 0; 749 } 750 // print "<!-- ${methName} -->\n"; 751 if (isset($dmap[$methName])) 752 { 753 if ($dmap[$methName]['signature']) 754 { 755 $sigs = array(); 756 $thesigs=$dmap[$methName]['signature']; 757 for($i=0; $i<sizeof($thesigs); $i++) 758 { 759 $cursig = array(); 760 $inSig = $thesigs[$i]; 761 for($j=0; $j<sizeof($inSig); $j++) 762 { 763 $cursig[] = CreateObject('phpgwapi.xmlrpcval',$inSig[$j], 'string'); 764 } 765 $sigs[] = CreateObject('phpgwapi.xmlrpcval',$cursig, 'array'); 766 } 767 $r = CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$sigs, 'array')); 768 } 769 else 770 { 771 $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval','undef', 'string')); 772 } 773 } 774 else 775 { 776 $r = CreateObject('phpgwapi.xmlrpcresp',0,$GLOBALS['xmlrpcerr']['introspect_unknown'],$GLOBALS['xmlrpcstr']['introspect_unknown']); 777 } 778 return $r; 779 } 780 781 $GLOBALS['_xmlrpcs_methodHelp_sig'] = array(array(xmlrpcString, xmlrpcString)); 782 $GLOBALS['_xmlrpcs_methodHelp_doc'] = 'Returns help text if defined for the method passed, otherwise returns an empty string'; 783 function _xmlrpcs_methodHelp($server, $m) 784 { 785 $methName = $m->getParam(0); 786 $methName = $methName->scalarval(); 787 if (ereg("^system\.", $methName)) 788 { 789 $dmap = $GLOBALS['_xmlrpcs_dmap']; 790 $sysCall=1; 791 } 792 else 793 { 794 $dmap = $server->dmap; 795 $sysCall=0; 796 } 797 // print "<!-- ${methName} -->\n"; 798 if (isset($dmap[$methName])) 799 { 800 if ($dmap[$methName]['docstring']) 801 { 802 $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval',$dmap[$methName]['docstring']),'string'); 803 } 804 else 805 { 806 $r = CreateObject('phpgwapi.xmlrpcresp', CreateObject('phpgwapi.xmlrpcval'), 'string'); 807 } 808 } 809 else 810 { 811 $r = CreateObject('phpgwapi.xmlrpcresp',0,$GLOBALS['xmlrpcerr']['introspect_unknown'],$GLOBALS['xmlrpcstr']['introspect_unknown']); 812 } 813 return $r; 814 } 815 816 $GLOBALS['_xmlrpcs_login_sig'] = array(array(xmlrpcStruct,xmlrpcStruct)); 817 $GLOBALS['_xmlrpcs_login_doc'] = 'eGroupWare client or server login via XML-RPC'; 818 function _xmlrpcs_login($server,$m) 819 { 820 $rdata = $m->getParam(0); 821 $data = $rdata->scalarval(); 822 823 if($data['server_name']) 824 { 825 $server_name = $data['server_name']->scalarval(); 826 } 827 if($data['domain']) 828 { 829 $domain = $data['domain']->scalarval(); 830 } 831 $username = $data['username']->scalarval(); 832 $password = $data['password']->scalarval(); 833 834 if($server_name) 835 { 836 list($sessionid,$kp3) = $GLOBALS['egw']->session->create_server($username.'@'.$server_name,$password,"text"); 837 } 838 else 839 { 840 if($domain) 841 { 842 $user = $username.'@'.$domain; 843 } 844 else 845 { 846 $user = $username; 847 } 848 $GLOBALS['login'] = $user; 849 850 $sessionid = $GLOBALS['egw']->session->create($user,$password,"text"); 851 $kp3 = $GLOBALS['egw']->session->kp3; 852 $domain = $GLOBALS['egw']->session->account_domain; 853 } 854 855 if($sessionid && $kp3) 856 { 857 $rtrn['domain'] = CreateObject('phpgwapi.xmlrpcval',$domain,'string'); 858 $rtrn['sessionid'] = CreateObject('phpgwapi.xmlrpcval',$sessionid,'string'); 859 $rtrn['kp3'] = CreateObject('phpgwapi.xmlrpcval',$kp3,'string'); 860 } 861 else 862 { 863 $rtrn['GOAWAY'] = CreateObject('phpgwapi.xmlrpcval','XOXO','string'); 864 } 865 return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$rtrn,'struct')); 866 } 867 868 $GLOBALS['_xmlrpcs_logout_sig'] = array(array(xmlrpcStruct,xmlrpcStruct)); 869 $GLOBALS['_xmlrpcs_logout_doc'] = 'eGroupWare client or server logout via XML-RPC'; 870 function _xmlrpcs_logout($server,$m) 871 { 872 $rdata = $m->getParam(0); 873 $data = $rdata->scalarval(); 874 875 $sessionid = $data['sessionid']->scalarval(); 876 $kp3 = $data['kp3']->scalarval(); 877 878 $later = $GLOBALS['egw']->session->destroy($sessionid,$kp3); 879 880 if ($later) 881 { 882 $rtrn['GOODBYE'] = CreateObject('phpgwapi.xmlrpcval','XOXO','string'); 883 } 884 else 885 { 886 /* This never happens, yet */ 887 $rtrn['OOPS'] = CreateObject('phpgwapi.xmlrpcval','WHAT?','string'); 888 } 889 return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$rtrn,'struct')); 890 } 891 892 $GLOBALS['_xmlrpcs_phpgw_api_version_sig'] = array(array(xmlrpcString)); 893 $GLOBALS['_xmlrpcs_phpgw_api_version_doc'] = 'Returns the eGroupWare API version'; 894 function _xmlrpcs_phpgw_api_version($server,$m) 895 { 896 $version = $GLOBALS['egw_info']['server']['versions']['phpgwapi']; 897 898 return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$version,'string')); 899 } 900 901 /* 902 $GLOBALS['_xmlrpcs_listApps_sig'] = array(array(xmlrpcStruct,xmlrpcString)); 903 $GLOBALS['_xmlrpcs_listApps_doc'] = 'Returns a list of installed phpgw apps'; 904 function _xmlrpcs_listApps($server,$m) 905 { 906 $m->getParam(0); 907 $GLOBALS['egw']->db->query("SELECT * FROM egw_applications WHERE app_enabled<3",__LINE__,__FILE__); 908 if($GLOBALS['egw']->db->num_rows()) 909 { 910 while($GLOBALS['egw']->db->next_record()) 911 { 912 $name = $GLOBALS['egw']->db->f('app_name'); 913 $title = $GLOBALS['egw']->db->f('app_title'); 914 $status = $GLOBALS['egw']->db->f('app_enabled'); 915 $version= $GLOBALS['egw']->db->f('app_version'); 916 $apps[$name] = CreateObject('phpgwapi.xmlrpcval', 917 array( 918 'title' => CreateObject('phpgwapi.xmlrpcval',$title,'string'), 919 'name' => CreateObject('phpgwapi.xmlrpcval',$name,'string'), 920 'status' => CreateObject('phpgwapi.xmlrpcval',$status,'string'), 921 'version'=> CreateObject('phpgwapi.xmlrpcval',$version,'string') 922 ), 923 'struct' 924 ); 925 } 926 } 927 return CreateObject('phpgwapi.xmlrpcresp',CreateObject('phpgwapi.xmlrpcval',$apps, 'struct')); 928 } 929 */ 930 931 $GLOBALS['_xmlrpcs_egw_time_sig'] = array(array(xmlrpcStruct)); 932 $GLOBALS['_xmlrpcs_egw_time_doc'] = 'returns system-time and -timezone and if loged in user-time and timezone'; 933 function _xmlrpcs_time($server,$m) 934 { 935 $return = array( 936 'system' => $GLOBALS['server']->date2iso8601(time()), 937 'system_tz_offset' => (int) date('Z'), 938 ); 939 if ($GLOBALS['server']->authed) 940 { 941 $tz_offset_s = 3600 * (int) $GLOBALS['egw_info']['user']['preferences']['common']['tz_offset']; 942 $return += array( 943 'user' => $GLOBALS['server']->date2iso8601(time()+$tz_offset_s), 944 'user_tz_offset' => (int) date('Z') + $tz_offset_s, 945 ); 946 } 947 return CreateObject( 948 'phpgwapi.xmlrpcresp', 949 $GLOBALS['server']->build_resp($return,true) 950 ); 951 } 952 953 /* Add the system functions to the server map */ 954 $GLOBALS['_xmlrpcs_dmap'] = array( 955 'system.listMethods' => array( 956 'function' => '_xmlrpcs_listMethods', 957 'signature' => $GLOBALS['_xmlrpcs_listMethods_sig'], 958 'docstring' => $GLOBALS['_xmlrpcs_listMethods_doc'] 959 ), 960 'system.methodHelp' => array( 961 'function' => '_xmlrpcs_methodHelp', 962 'signature' => $GLOBALS['_xmlrpcs_methodHelp_sig'], 963 'docstring' => $GLOBALS['_xmlrpcs_methodHelp_doc'] 964 ), 965 'system.methodSignature' => array( 966 'function' => '_xmlrpcs_methodSignature', 967 'signature' => $GLOBALS['_xmlrpcs_methodSignature_sig'], 968 'docstring' => $GLOBALS['_xmlrpcs_methodSignature_doc'] 969 ), 970 'system.login' => array( 971 'function' => '_xmlrpcs_login', 972 'signature' => $GLOBALS['_xmlrpcs_login_sig'], 973 'docstring' => $GLOBALS['_xmlrpcs_login_doc'] 974 ), 975 'system.logout' => array( 976 'function' => '_xmlrpcs_logout', 977 'signature' => $GLOBALS['_xmlrpcs_logout_sig'], 978 'docstring' => $GLOBALS['_xmlrpcs_logout_doc'] 979 ), 980 'system.phpgw_api_version' => array( 981 'function' => '_xmlrpcs_phpgw_api_version', 982 'signature' => $GLOBALS['_xmlrpcs_phpgw_api_version_sig'], 983 'docstring' => $GLOBALS['_xmlrpcs_phpgw_api_version_doc'] 984 ), 985 /* 986 'system.listApps' => array( 987 'function' => '_xmlrpcs_listApps', 988 'signature' => $GLOBALS['_xmlrpcs_listApps_sig'], 989 'docstring' => $GLOBALS['_xmlrpcs_listApps_doc'] 990 ), 991 */ 992 'system.time' => array( 993 'function' => '_xmlrpcs_time', 994 'signature' => $GLOBALS['_xmlrpcs_egw_time_sig'], 995 'docstring' => $GLOBALS['_xmlrpcs_egw_time_doc'] 996 ) 997 ); 998 999 $GLOBALS['_xmlrpc_debuginfo'] = ''; 1000 function xmlrpc_debugmsg($m) 1001 { 1002 $GLOBALS['_xmlrpc_debuginfo'] .= $m . "\n"; 1003 } 1004 ?>
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 |