| [ PHPXref.com ] | [ Generated: Sun Jul 20 19:13:40 2008 ] | [ osCommRes 1.2.0 ] |
| [ Index ] [ Variables ] [ Functions ] [ Classes ] [ Constants ] [ Statistics ] | ||
[Summary view] [Print] [Text view]
1 <?php // -*-c++-*- 2 // by Edd Dumbill (C) 1999-2001 3 // <edd@usefulinc.com> 4 // $Id: xmlrpc.inc,v 1.1 2004/03/08 21:21:16 schst Exp $ 5 6 7 // Copyright (c) 1999,2000,2001 Edd Dumbill. 8 // All rights reserved. 9 // 10 // Redistribution and use in source and binary forms, with or without 11 // modification, are permitted provided that the following conditions 12 // are met: 13 // 14 // * Redistributions of source code must retain the above copyright 15 // notice, this list of conditions and the following disclaimer. 16 // 17 // * Redistributions in binary form must reproduce the above 18 // copyright notice, this list of conditions and the following 19 // disclaimer in the documentation and/or other materials provided 20 // with the distribution. 21 // 22 // * Neither the name of the "XML-RPC for PHP" nor the names of its 23 // contributors may be used to endorse or promote products derived 24 // from this software without specific prior written permission. 25 // 26 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 29 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 30 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 31 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 32 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 33 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 35 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 37 // OF THE POSSIBILITY OF SUCH DAMAGE. 38 39 if (!function_exists('xml_parser_create')) { 40 // Win 32 fix. From: "Leo West" <lwest@imaginet.fr> 41 if($WINDIR) { 42 dl("php3_xml.dll"); 43 } else { 44 dl("xml.so"); 45 } 46 } 47 48 $xmlrpcI4="i4"; 49 $xmlrpcInt="int"; 50 $xmlrpcBoolean="boolean"; 51 $xmlrpcDouble="double"; 52 $xmlrpcString="string"; 53 $xmlrpcDateTime="dateTime.iso8601"; 54 $xmlrpcBase64="base64"; 55 $xmlrpcArray="array"; 56 $xmlrpcStruct="struct"; 57 58 59 $xmlrpcTypes=array($xmlrpcI4 => 1, 60 $xmlrpcInt => 1, 61 $xmlrpcBoolean => 1, 62 $xmlrpcString => 1, 63 $xmlrpcDouble => 1, 64 $xmlrpcDateTime => 1, 65 $xmlrpcBase64 => 1, 66 $xmlrpcArray => 2, 67 $xmlrpcStruct => 3); 68 69 $xmlEntities=array( "amp" => "&", 70 "quot" => '"', 71 "lt" => "<", 72 "gt" => ">", 73 "apos" => "'"); 74 75 $xmlrpcerr["unknown_method"]=1; 76 $xmlrpcstr["unknown_method"]="Unknown method"; 77 $xmlrpcerr["invalid_return"]=2; 78 $xmlrpcstr["invalid_return"]="Invalid return payload: enabling debugging to examine incoming payload"; 79 $xmlrpcerr["incorrect_params"]=3; 80 $xmlrpcstr["incorrect_params"]="Incorrect parameters passed to method"; 81 $xmlrpcerr["introspect_unknown"]=4; 82 $xmlrpcstr["introspect_unknown"]="Can't introspect: method unknown"; 83 $xmlrpcerr["http_error"]=5; 84 $xmlrpcstr["http_error"]="Didn't receive 200 OK from remote server."; 85 $xmlrpcerr["no_data"]=6; 86 $xmlrpcstr["no_data"]="No data received from server."; 87 $xmlrpcerr["no_ssl"]=7; 88 $xmlrpcstr["no_ssl"]="No SSL support compiled in."; 89 $xmlrpcerr["curl_fail"]=8; 90 $xmlrpcstr["curl_fail"]="CURL error"; 91 92 $xmlrpc_defencoding="UTF-8"; 93 94 $xmlrpcName="XML-RPC for PHP"; 95 $xmlrpcVersion="1.01"; 96 97 // let user errors start at 800 98 $xmlrpcerruser=800; 99 // let XML parse errors start at 100 100 $xmlrpcerrxml=100; 101 102 // formulate backslashes for escaping regexp 103 $xmlrpc_backslash=chr(92).chr(92); 104 105 // used to store state during parsing 106 // quick explanation of components: 107 // st - used to build up a string for evaluation 108 // ac - used to accumulate values 109 // qt - used to decide if quotes are needed for evaluation 110 // cm - used to denote struct or array (comma needed) 111 // isf - used to indicate a fault 112 // lv - used to indicate "looking for a value": implements 113 // the logic to allow values with no types to be strings 114 // params - used to store parameters in method calls 115 // method - used to store method name 116 117 $_xh=array(); 118 119 function xmlrpc_entity_decode($string) { 120 $top=split("&", $string); 121 $op=""; 122 $i=0; 123 while($i<sizeof($top)) { 124 if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) { 125 $op.=ereg_replace("^[#a-zA-Z0-9]+;", 126 xmlrpc_lookup_entity($regs[1]), 127 $top[$i]); 128 } else { 129 if ($i==0) 130 $op=$top[$i]; 131 else 132 $op.="&" . $top[$i]; 133 } 134 $i++; 135 } 136 return $op; 137 } 138 139 function xmlrpc_lookup_entity($ent) { 140 global $xmlEntities; 141 142 if (isset($xmlEntities[strtolower($ent)])) 143 return $xmlEntities[strtolower($ent)]; 144 if (ereg("^#([0-9]+)$", $ent, $regs)) 145 return chr($regs[1]); 146 return "?"; 147 } 148 149 function xmlrpc_se($parser, $name, $attrs) { 150 global $_xh, $xmlrpcDateTime, $xmlrpcString; 151 152 switch($name) { 153 case "STRUCT": 154 case "ARRAY": 155 $_xh[$parser]['st'].="array("; 156 $_xh[$parser]['cm']++; 157 // this last line turns quoting off 158 // this means if we get an empty array we'll 159 // simply get a bit of whitespace in the eval 160 $_xh[$parser]['qt']=0; 161 break; 162 case "NAME": 163 $_xh[$parser]['st'].="'"; $_xh[$parser]['ac']=""; 164 break; 165 case "FAULT": 166 $_xh[$parser]['isf']=1; 167 break; 168 case "PARAM": 169 $_xh[$parser]['st']=""; 170 break; 171 case "VALUE": 172 $_xh[$parser]['st'].="new xmlrpcval("; 173 $_xh[$parser]['vt']=$xmlrpcString; 174 $_xh[$parser]['ac']=""; 175 $_xh[$parser]['qt']=0; 176 $_xh[$parser]['lv']=1; 177 // look for a value: if this is still 1 by the 178 // time we reach the first data segment then the type is string 179 // by implication and we need to add in a quote 180 break; 181 182 case "I4": 183 case "INT": 184 case "STRING": 185 case "BOOLEAN": 186 case "DOUBLE": 187 case "DATETIME.ISO8601": 188 case "BASE64": 189 $_xh[$parser]['ac']=""; // reset the accumulator 190 191 if ($name=="DATETIME.ISO8601" || $name=="STRING") { 192 $_xh[$parser]['qt']=1; 193 if ($name=="DATETIME.ISO8601") 194 $_xh[$parser]['vt']=$xmlrpcDateTime; 195 } else if ($name=="BASE64") { 196 $_xh[$parser]['qt']=2; 197 } else { 198 // No quoting is required here -- but 199 // at the end of the element we must check 200 // for data format errors. 201 $_xh[$parser]['qt']=0; 202 } 203 break; 204 case "MEMBER": 205 $_xh[$parser]['ac']=""; 206 break; 207 default: 208 break; 209 } 210 211 if ($name!="VALUE") $_xh[$parser]['lv']=0; 212 } 213 214 function xmlrpc_ee($parser, $name) { 215 global $_xh,$xmlrpcTypes,$xmlrpcString; 216 217 switch($name) { 218 case "STRUCT": 219 case "ARRAY": 220 if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',') { 221 $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1); 222 } 223 $_xh[$parser]['st'].=")"; 224 $_xh[$parser]['vt']=strtolower($name); 225 $_xh[$parser]['cm']--; 226 break; 227 case "NAME": 228 $_xh[$parser]['st'].= $_xh[$parser]['ac'] . "' => "; 229 break; 230 case "BOOLEAN": 231 // special case here: we translate boolean 1 or 0 into PHP 232 // constants true or false 233 if ($_xh[$parser]['ac']=='1') 234 $_xh[$parser]['ac']="true"; 235 else 236 $_xh[$parser]['ac']="false"; 237 $_xh[$parser]['vt']=strtolower($name); 238 // Drop through intentionally. 239 case "I4": 240 case "INT": 241 case "STRING": 242 case "DOUBLE": 243 case "DATETIME.ISO8601": 244 case "BASE64": 245 if ($_xh[$parser]['qt']==1) { 246 // we use double quotes rather than single so backslashification works OK 247 $_xh[$parser]['st'].="\"". $_xh[$parser]['ac'] . "\""; 248 } else if ($_xh[$parser]['qt']==2) { 249 $_xh[$parser]['st'].="base64_decode('". $_xh[$parser]['ac'] . "')"; 250 } else if ($name=="BOOLEAN") { 251 $_xh[$parser]['st'].=$_xh[$parser]['ac']; 252 } else { 253 // we have an I4, INT or a DOUBLE 254 // we must check that only 0123456789-.<space> are characters here 255 if (!ereg("^\-?[0123456789 \t\.]+$", $_xh[$parser]['ac'])) { 256 // TODO: find a better way of throwing an error 257 // than this! 258 error_log("XML-RPC: non numeric value received in INT or DOUBLE"); 259 $_xh[$parser]['st'].="ERROR_NON_NUMERIC_FOUND"; 260 } else { 261 // it's ok, add it on 262 $_xh[$parser]['st'].=$_xh[$parser]['ac']; 263 } 264 } 265 $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; 266 $_xh[$parser]['lv']=3; // indicate we've found a value 267 break; 268 case "VALUE": 269 // deal with a string value 270 if (strlen($_xh[$parser]['ac'])>0 && 271 $_xh[$parser]['vt']==$xmlrpcString) { 272 $_xh[$parser]['st'].="\"". $_xh[$parser]['ac'] . "\""; 273 } 274 // This if() detects if no scalar was inside <VALUE></VALUE> 275 // and pads an empty "". 276 if($_xh[$parser]['st'][strlen($_xh[$parser]['st'])-1] == '(') { 277 $_xh[$parser]['st'].= '""'; 278 } 279 $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')"; 280 if ($_xh[$parser]['cm']) $_xh[$parser]['st'].=","; 281 break; 282 case "MEMBER": 283 $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; 284 break; 285 case "DATA": 286 $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; 287 break; 288 case "PARAM": 289 $_xh[$parser]['params'][]=$_xh[$parser]['st']; 290 break; 291 case "METHODNAME": 292 $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", "", 293 $_xh[$parser]['ac']); 294 break; 295 case "BOOLEAN": 296 // special case here: we translate boolean 1 or 0 into PHP 297 // constants true or false 298 if ($_xh[$parser]['ac']=='1') 299 $_xh[$parser]['ac']="true"; 300 else 301 $_xh[$parser]['ac']="false"; 302 $_xh[$parser]['vt']=strtolower($name); 303 break; 304 default: 305 break; 306 } 307 // if it's a valid type name, set the type 308 if (isset($xmlrpcTypes[strtolower($name)])) { 309 $_xh[$parser]['vt']=strtolower($name); 310 } 311 312 } 313 314 function xmlrpc_cd($parser, $data) 315 { 316 global $_xh, $xmlrpc_backslash; 317 318 //if (ereg("^[\n\r \t]+$", $data)) return; 319 // print "adding [${data}]\n"; 320 321 if ($_xh[$parser]['lv']!=3) { 322 // "lookforvalue==3" means that we've found an entire value 323 // and should discard any further character data 324 if ($_xh[$parser]['lv']==1) { 325 // if we've found text and we're just in a <value> then 326 // turn quoting on, as this will be a string 327 $_xh[$parser]['qt']=1; 328 // and say we've found a value 329 $_xh[$parser]['lv']=2; 330 } 331 // replace characters that eval would 332 // do special things with 333 $_xh[$parser]['ac'].=str_replace('$', '\$', 334 str_replace('"', '\"', str_replace(chr(92), 335 $xmlrpc_backslash, $data))); 336 } 337 } 338 339 function xmlrpc_dh($parser, $data) 340 { 341 global $_xh; 342 if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") { 343 if ($_xh[$parser]['lv']==1) { 344 $_xh[$parser]['qt']=1; 345 $_xh[$parser]['lv']=2; 346 } 347 $_xh[$parser]['ac'].=str_replace('$', '\$', 348 str_replace('"', '\"', str_replace(chr(92), 349 $xmlrpc_backslash, $data))); 350 } 351 } 352 353 class xmlrpc_client { 354 var $path; 355 var $server; 356 var $port; 357 var $errno; 358 var $errstring; 359 var $debug=0; 360 var $username=""; 361 var $password=""; 362 var $cert=""; 363 var $certpass=""; 364 365 function xmlrpc_client($path, $server, $port=0) { 366 $this->port=$port; $this->server=$server; $this->path=$path; 367 } 368 369 function setDebug($in) { 370 if ($in) { 371 $this->debug=1; 372 } else { 373 $this->debug=0; 374 } 375 } 376 377 function setCredentials($u, $p) { 378 $this->username=$u; 379 $this->password=$p; 380 } 381 382 function setCertificate($cert, $certpass) { 383 $this->cert = $cert; 384 $this->certpass = $certpass; 385 } 386 387 function send($msg, $timeout=0, $method='http') { 388 // where msg is an xmlrpcmsg 389 $msg->debug=$this->debug; 390 391 if ($method == 'https') { 392 return $this->sendPayloadHTTPS($msg, 393 $this->server, 394 $this->port, $timeout, 395 $this->username, $this->password, 396 $this->cert, 397 $this->certpass); 398 } else { 399 return $this->sendPayloadHTTP10($msg, $this->server, $this->port, 400 $timeout, $this->username, 401 $this->password); 402 } 403 } 404 405 function sendPayloadHTTP10($msg, $server, $port, $timeout=0, 406 $username="", $password="") { 407 if ($port==0) $port=80; 408 if($timeout>0) 409 $fp=fsockopen($server, $port, 410 &$this->errno, &$this->errstr, $timeout); 411 else 412 $fp=fsockopen($server, $port, 413 &$this->errno, &$this->errstr); 414 if (!$fp) { 415 return 0; 416 } 417 // Only create the payload if it was not created previously 418 if(empty($msg->payload)) $msg->createPayload(); 419 420 // thanks to Grant Rauscher <grant7@firstworld.net> 421 // for this 422 $credentials=""; 423 if ($username!="") { 424 $credentials="Authorization: Basic " . 425 base64_encode($username . ":" . $password) . "\r\n"; 426 } 427 428 $op= "POST " . $this->path. " HTTP/1.0\r\nUser-Agent: PHP XMLRPC 1.0\r\n" . 429 "Host: ". $this->server . "\r\n" . 430 $credentials . 431 "Content-Type: text/xml\r\nContent-Length: " . 432 strlen($msg->payload) . "\r\n\r\n" . 433 $msg->payload; 434 435 if (!fputs($fp, $op, strlen($op))) { 436 $this->errstr="Write error"; 437 return 0; 438 } 439 $resp=$msg->parseResponseFile($fp); 440 fclose($fp); 441 return $resp; 442 } 443 444 // contributed by Justin Miller <justin@voxel.net> 445 // requires curl to be built into PHP 446 function sendPayloadHTTPS($msg, $server, $port, $timeout=0, 447 $username="", $password="", $cert="", 448 $certpass="") { 449 global $xmlrpcerr, $xmlrpcstr; 450 if ($port == 0) $port = 443; 451 452 // Only create the payload if it was not created previously 453 if(empty($msg->payload)) $msg->createPayload(); 454 455 if (!function_exists("curl_init")) { 456 $r=new xmlrpcresp(0, $xmlrpcerr["no_ssl"], 457 $xmlrpcstr["no_ssl"]); 458 return $r; 459 } 460 461 $curl = curl_init("https://" . $server . ':' . $port . 462 $this->path); 463 464 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 465 // results into variable 466 if ($this->debug) { 467 curl_setopt($curl, CURLOPT_VERBOSE, 1); 468 } 469 curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC 1.0'); 470 // required for XMLRPC 471 curl_setopt($curl, CURLOPT_POST, 1); 472 // post the data 473 curl_setopt($curl, CURLOPT_POSTFIELDS, $msg->payload); 474 // the data 475 curl_setopt($curl, CURLOPT_HEADER, 1); 476 // return the header too 477 curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); 478 // required for XMLRPC 479 if ($timeout) curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : 480 $timeout - 1); 481 // timeout is borked 482 if ($username && $password) curl_setopt($curl, CURLOPT_USERPWD, 483 "$username:$password"); 484 // set auth stuff 485 if ($cert) curl_setopt($curl, CURLOPT_SSLCERT, $cert); 486 // set cert file 487 if ($certpass) curl_setopt($curl, CURLOPT_SSLCERTPASSWD, 488 $certpass); 489 // set cert password 490 491 $result = curl_exec($curl); 492 493 if (!$result) { 494 $resp=new xmlrpcresp(0, 495 $xmlrpcerr["curl_fail"], 496 $xmlrpcstr["curl_fail"]. ": ". 497 curl_error($curl)); 498 } else { 499 $resp = $msg->parseResponse($result); 500 } 501 curl_close($curl); 502 return $resp; 503 } 504 505 } // end class xmlrpc_client 506 507 class xmlrpcresp { 508 var $xv; 509 var $fn; 510 var