1 | <?php // -*-c++-*- |
---|
2 | // by Edd Dumbill (C) 1999-2001 |
---|
3 | // <[email protected]> |
---|
4 | // $Id: class-xmlrpc.php 1335 2004-05-21 21:29:57Z michelvaldrighi $ |
---|
5 | |
---|
6 | |
---|
7 | # additional fixes for case of missing xml extension file by Michel Valdrighi <[email protected]> |
---|
8 | |
---|
9 | |
---|
10 | // Copyright (c) 1999,2000,2001 Edd Dumbill. |
---|
11 | // All rights reserved. |
---|
12 | // |
---|
13 | // Redistribution and use in source and binary forms, with or without |
---|
14 | // modification, are permitted provided that the following conditions |
---|
15 | // are met: |
---|
16 | // |
---|
17 | // * Redistributions of source code must retain the above copyright |
---|
18 | // notice, this list of conditions and the following disclaimer. |
---|
19 | // |
---|
20 | // * Redistributions in binary form must reproduce the above |
---|
21 | // copyright notice, this list of conditions and the following |
---|
22 | // disclaimer in the documentation and/or other materials provided |
---|
23 | // with the distribution. |
---|
24 | // |
---|
25 | // * Neither the name of the "XML-RPC for PHP" nor the names of its |
---|
26 | // contributors may be used to endorse or promote products derived |
---|
27 | // from this software without specific prior written permission. |
---|
28 | // |
---|
29 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
30 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
31 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
---|
32 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
---|
33 | // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
34 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
---|
35 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
---|
36 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
37 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
---|
38 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
---|
39 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
---|
40 | // OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
41 | |
---|
42 | |
---|
43 | # b2 fix. some servers have stupid warnings |
---|
44 | #error_reporting(0); |
---|
45 | |
---|
46 | if (!function_exists('logIO')) { |
---|
47 | function logIO($m="",$n="") { |
---|
48 | return(true); |
---|
49 | } |
---|
50 | } |
---|
51 | |
---|
52 | |
---|
53 | if (!function_exists('xml_parser_create')) { |
---|
54 | // Win 32 fix. From: "Leo West" <[email protected]> |
---|
55 | // Fix for missing extension file. From: "Michel Valdrighi" <[email protected]> |
---|
56 | if($WINDIR) { |
---|
57 | if (@dl("php3_xml.dll")) { |
---|
58 | define("CANUSEXMLRPC", 1); |
---|
59 | } else { |
---|
60 | define("CANUSEXMLRPC", 0); |
---|
61 | } |
---|
62 | } else { |
---|
63 | if (@dl("xml.so")) { |
---|
64 | define("CANUSEXMLRPC", 1); |
---|
65 | } else { |
---|
66 | define("CANUSEXMLRPC", 0); |
---|
67 | } |
---|
68 | } |
---|
69 | } else { |
---|
70 | define("CANUSEXMLRPC", 1); |
---|
71 | } |
---|
72 | |
---|
73 | if (CANUSEXMLRPC == 1) { |
---|
74 | |
---|
75 | $xmlrpcI4="i4"; |
---|
76 | $xmlrpcInt="int"; |
---|
77 | $xmlrpcBoolean="boolean"; |
---|
78 | $xmlrpcDouble="double"; |
---|
79 | $xmlrpcString="string"; |
---|
80 | $xmlrpcDateTime="dateTime.iso8601"; |
---|
81 | $xmlrpcBase64="base64"; |
---|
82 | $xmlrpcArray="array"; |
---|
83 | $xmlrpcStruct="struct"; |
---|
84 | |
---|
85 | |
---|
86 | $xmlrpcTypes=array($xmlrpcI4 => 1, |
---|
87 | $xmlrpcInt => 1, |
---|
88 | $xmlrpcBoolean => 1, |
---|
89 | $xmlrpcString => 1, |
---|
90 | $xmlrpcDouble => 1, |
---|
91 | $xmlrpcDateTime => 1, |
---|
92 | $xmlrpcBase64 => 1, |
---|
93 | $xmlrpcArray => 2, |
---|
94 | $xmlrpcStruct => 3); |
---|
95 | |
---|
96 | $xmlEntities=array( "amp" => "&", |
---|
97 | "quot" => '"', |
---|
98 | "lt" => "<", |
---|
99 | "gt" => ">", |
---|
100 | "apos" => "'"); |
---|
101 | |
---|
102 | $xmlrpcerr["unknown_method"]=1; |
---|
103 | $xmlrpcstr["unknown_method"]="Unknown method"; |
---|
104 | $xmlrpcerr["invalid_return"]=2; |
---|
105 | $xmlrpcstr["invalid_return"]="Invalid return payload: enabling debugging to examine incoming payload"; |
---|
106 | $xmlrpcerr["incorrect_params"]=3; |
---|
107 | $xmlrpcstr["incorrect_params"]="Incorrect parameters passed to method"; |
---|
108 | $xmlrpcerr["introspect_unknown"]=4; |
---|
109 | $xmlrpcstr["introspect_unknown"]="Can't introspect: method unknown"; |
---|
110 | $xmlrpcerr["http_error"]=5; |
---|
111 | $xmlrpcstr["http_error"]="Didn't receive 200 OK from remote server."; |
---|
112 | $xmlrpcerr["no_data"]=6; |
---|
113 | $xmlrpcstr["no_data"]="No data received from server."; |
---|
114 | $xmlrpcerr["no_ssl"]=7; |
---|
115 | $xmlrpcstr["no_ssl"]="No SSL support compiled in."; |
---|
116 | $xmlrpcerr["curl_fail"]=8; |
---|
117 | $xmlrpcstr["curl_fail"]="CURL error"; |
---|
118 | |
---|
119 | $xmlrpc_defencoding="UTF-8"; |
---|
120 | |
---|
121 | $xmlrpcName="XML-RPC for PHP"; |
---|
122 | $xmlrpcVersion="1.02"; |
---|
123 | |
---|
124 | // let user errors start at 800 |
---|
125 | $xmlrpcerruser=800; |
---|
126 | // let XML parse errors start at 100 |
---|
127 | $xmlrpcerrxml=100; |
---|
128 | |
---|
129 | // formulate backslashes for escaping regexp |
---|
130 | $xmlrpc_backslash=chr(92).chr(92); |
---|
131 | |
---|
132 | // used to store state during parsing |
---|
133 | // quick explanation of components: |
---|
134 | // st - used to build up a string for evaluation |
---|
135 | // ac - used to accumulate values |
---|
136 | // qt - used to decide if quotes are needed for evaluation |
---|
137 | // cm - used to denote struct or array (comma needed) |
---|
138 | // isf - used to indicate a fault |
---|
139 | // lv - used to indicate "looking for a value": implements |
---|
140 | // the logic to allow values with no types to be strings |
---|
141 | // params - used to store parameters in method calls |
---|
142 | // method - used to store method name |
---|
143 | |
---|
144 | $_xh=array(); |
---|
145 | |
---|
146 | function xmlrpc_entity_decode($string) { |
---|
147 | $top=split("&", $string); |
---|
148 | $op=""; |
---|
149 | $i=0; |
---|
150 | while($i<sizeof($top)) { |
---|
151 | if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) { |
---|
152 | $op.=ereg_replace("^[#a-zA-Z0-9]+;", |
---|
153 | xmlrpc_lookup_entity($regs[1]), |
---|
154 | $top[$i]); |
---|
155 | } else { |
---|
156 | if ($i==0) |
---|
157 | $op=$top[$i]; |
---|
158 | else |
---|
159 | $op.="&" . $top[$i]; |
---|
160 | } |
---|
161 | $i++; |
---|
162 | } |
---|
163 | return $op; |
---|
164 | } |
---|
165 | |
---|
166 | function xmlrpc_lookup_entity($ent) { |
---|
167 | global $xmlEntities; |
---|
168 | |
---|
169 | if (isset($xmlEntities[strtolower($ent)])) |
---|
170 | return $xmlEntities[strtolower($ent)]; |
---|
171 | if (ereg("^#([0-9]+)$", $ent, $regs)) |
---|
172 | return chr($regs[1]); |
---|
173 | return "?"; |
---|
174 | } |
---|
175 | |
---|
176 | function xmlrpc_se($parser, $name, $attrs) { |
---|
177 | global $_xh, $xmlrpcDateTime, $xmlrpcString; |
---|
178 | |
---|
179 | switch($name) { |
---|
180 | case "STRUCT": |
---|
181 | case "ARRAY": |
---|
182 | $_xh[$parser]['st'].="array("; |
---|
183 | $_xh[$parser]['cm']++; |
---|
184 | // this last line turns quoting off |
---|
185 | // this means if we get an empty array we'll |
---|
186 | // simply get a bit of whitespace in the eval |
---|
187 | $_xh[$parser]['qt']=0; |
---|
188 | break; |
---|
189 | case "NAME": |
---|
190 | $_xh[$parser]['st'].="'"; $_xh[$parser]['ac']=""; |
---|
191 | break; |
---|
192 | case "FAULT": |
---|
193 | $_xh[$parser]['isf']=1; |
---|
194 | break; |
---|
195 | case "PARAM": |
---|
196 | $_xh[$parser]['st']=""; |
---|
197 | break; |
---|
198 | case "VALUE": |
---|
199 | $_xh[$parser]['st'].="new xmlrpcval("; |
---|
200 | $_xh[$parser]['vt']=$xmlrpcString; |
---|
201 | $_xh[$parser]['ac']=""; |
---|
202 | $_xh[$parser]['qt']=0; |
---|
203 | $_xh[$parser]['lv']=1; |
---|
204 | // look for a value: if this is still 1 by the |
---|
205 | // time we reach the first data segment then the type is string |
---|
206 | // by implication and we need to add in a quote |
---|
207 | break; |
---|
208 | |
---|
209 | case "I4": |
---|
210 | case "INT": |
---|
211 | case "STRING": |
---|
212 | case "BOOLEAN": |
---|
213 | case "DOUBLE": |
---|
214 | case "DATETIME.ISO8601": |
---|
215 | case "BASE64": |
---|
216 | $_xh[$parser]['ac']=""; // reset the accumulator |
---|
217 | |
---|
218 | if ($name=="DATETIME.ISO8601" || $name=="STRING") { |
---|
219 | $_xh[$parser]['qt']=1; |
---|
220 | if ($name=="DATETIME.ISO8601") |
---|
221 | $_xh[$parser]['vt']=$xmlrpcDateTime; |
---|
222 | } else if ($name=="BASE64") { |
---|
223 | $_xh[$parser]['qt']=2; |
---|
224 | } else { |
---|
225 | // No quoting is required here -- but |
---|
226 | // at the end of the element we must check |
---|
227 | // for data format errors. |
---|
228 | $_xh[$parser]['qt']=0; |
---|
229 | } |
---|
230 | break; |
---|
231 | case "MEMBER": |
---|
232 | $_xh[$parser]['ac']=""; |
---|
233 | break; |
---|
234 | default: |
---|
235 | break; |
---|
236 | } |
---|
237 | |
---|
238 | if ($name!="VALUE") $_xh[$parser]['lv']=0; |
---|
239 | } |
---|
240 | |
---|
241 | function xmlrpc_ee($parser, $name) { |
---|
242 | global $_xh,$xmlrpcTypes,$xmlrpcString; |
---|
243 | |
---|
244 | switch($name) { |
---|
245 | case "STRUCT": |
---|
246 | case "ARRAY": |
---|
247 | if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',') { |
---|
248 | $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1); |
---|
249 | } |
---|
250 | $_xh[$parser]['st'].=")"; |
---|
251 | $_xh[$parser]['vt']=strtolower($name); |
---|
252 | $_xh[$parser]['cm']--; |
---|
253 | break; |
---|
254 | case "NAME": |
---|
255 | $_xh[$parser]['st'].= $_xh[$parser]['ac'] . "' => "; |
---|
256 | break; |
---|
257 | case "BOOLEAN": |
---|
258 | // special case here: we translate boolean 1 or 0 into PHP |
---|
259 | // constants true or false |
---|
260 | if ($_xh[$parser]['ac']=='1') |
---|
261 | $_xh[$parser]['ac']="true"; |
---|
262 | else |
---|
263 | $_xh[$parser]['ac']="false"; |
---|
264 | $_xh[$parser]['vt']=strtolower($name); |
---|
265 | // Drop through intentionally. |
---|
266 | case "I4": |
---|
267 | case "INT": |
---|
268 | case "STRING": |
---|
269 | case "DOUBLE": |
---|
270 | case "DATETIME.ISO8601": |
---|
271 | case "BASE64": |
---|
272 | if ($_xh[$parser]['qt']==1) { |
---|
273 | // we use double quotes rather than single so backslashification works OK |
---|
274 | $_xh[$parser]['st'].="\"". $_xh[$parser]['ac'] . "\""; |
---|
275 | } else if ($_xh[$parser]['qt']==2) { |
---|
276 | $_xh[$parser]['st'].="base64_decode('". $_xh[$parser]['ac'] . "')"; |
---|
277 | } else if ($name=="BOOLEAN") { |
---|
278 | $_xh[$parser]['st'].=$_xh[$parser]['ac']; |
---|
279 | } else { |
---|
280 | // we have an I4, INT or a DOUBLE |
---|
281 | // we must check that only 0123456789-.<space> are characters here |
---|
282 | if (!ereg("^\-?[0123456789 \t\.]+$", $_xh[$parser]['ac'])) { |
---|
283 | // TODO: find a better way of throwing an error |
---|
284 | // than this! |
---|
285 | error_log("XML-RPC: non numeric value received in INT or DOUBLE"); |
---|
286 | $_xh[$parser]['st'].="ERROR_NON_NUMERIC_FOUND"; |
---|
287 | } else { |
---|
288 | // it's ok, add it on |
---|
289 | $_xh[$parser]['st'].=$_xh[$parser]['ac']; |
---|
290 | } |
---|
291 | } |
---|
292 | $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; |
---|
293 | $_xh[$parser]['lv']=3; // indicate we've found a value |
---|
294 | break; |
---|
295 | case "VALUE": |
---|
296 | // deal with a string value |
---|
297 | if (strlen($_xh[$parser]['ac'])>0 && |
---|
298 | $_xh[$parser]['vt']==$xmlrpcString) { |
---|
299 | $_xh[$parser]['st'].="\"". $_xh[$parser]['ac'] . "\""; |
---|
300 | } |
---|
301 | // This if() detects if no scalar was inside <VALUE></VALUE> |
---|
302 | // and pads an empty "". |
---|
303 | if($_xh[$parser]['st'][strlen($_xh[$parser]['st'])-1] == '(') { |
---|
304 | $_xh[$parser]['st'].= '""'; |
---|
305 | } |
---|
306 | $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')"; |
---|
307 | if ($_xh[$parser]['cm']) $_xh[$parser]['st'].=","; |
---|
308 | break; |
---|
309 | case "MEMBER": |
---|
310 | $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; |
---|
311 | break; |
---|
312 | case "DATA": |
---|
313 | $_xh[$parser]['ac']=""; $_xh[$parser]['qt']=0; |
---|
314 | break; |
---|
315 | case "PARAM": |
---|
316 | $_xh[$parser]['params'][]=$_xh[$parser]['st']; |
---|
317 | break; |
---|
318 | case "METHODNAME": |
---|
319 | $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", "", |
---|
320 | $_xh[$parser]['ac']); |
---|
321 | break; |
---|
322 | case "BOOLEAN": |
---|
323 | // special case here: we translate boolean 1 or 0 into PHP |
---|
324 | // constants true or false |
---|
325 | if ($_xh[$parser]['ac']=='1') |
---|
326 | $_xh[$parser]['ac']="true"; |
---|
327 | else |
---|
328 | $_xh[$parser]['ac']="false"; |
---|
329 | $_xh[$parser]['vt']=strtolower($name); |
---|
330 | break; |
---|
331 | default: |
---|
332 | break; |
---|
333 | } |
---|
334 | // if it's a valid type name, set the type |
---|
335 | if (isset($xmlrpcTypes[strtolower($name)])) { |
---|
336 | $_xh[$parser]['vt']=strtolower($name); |
---|
337 | } |
---|
338 | |
---|
339 | } |
---|
340 | |
---|
341 | function xmlrpc_cd($parser, $data) |
---|
342 | { |
---|
343 | global $_xh, $xmlrpc_backslash; |
---|
344 | |
---|
345 | //if (ereg("^[\n\r \t]+$", $data)) return; |
---|
346 | // print "adding [${data}]\n"; |
---|
347 | |
---|
348 | if ($_xh[$parser]['lv']!=3) { |
---|
349 | // "lookforvalue==3" means that we've found an entire value |
---|
350 | // and should discard any further character data |
---|
351 | if ($_xh[$parser]['lv']==1) { |
---|
352 | // if we've found text and we're just in a <value> then |
---|
353 | // turn quoting on, as this will be a string |
---|
354 | $_xh[$parser]['qt']=1; |
---|
355 | // and say we've found a value |
---|
356 | $_xh[$parser]['lv']=2; |
---|
357 | } |
---|
358 | // replace characters that eval would |
---|
359 | // do special things with |
---|
360 | $_xh[$parser]['ac'].=str_replace('$', '\$', |
---|
361 | str_replace('"', '\"', str_replace(chr(92), |
---|
362 | $xmlrpc_backslash, $data))); |
---|
363 | } |
---|
364 | } |
---|
365 | |
---|
366 | function xmlrpc_dh($parser, $data) |
---|
367 | { |
---|
368 | global $_xh; |
---|
369 | if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") { |
---|
370 | if ($_xh[$parser]['lv']==1) { |
---|
371 | $_xh[$parser]['qt']=1; |
---|
372 | $_xh[$parser]['lv']=2; |
---|
373 | } |
---|
374 | $_xh[$parser]['ac'].=str_replace('$', '\$', |
---|
375 | str_replace('"', '\"', str_replace(chr(92), |
---|
376 | $xmlrpc_backslash, $data))); |
---|
377 | } |
---|
378 | } |
---|
379 | |
---|
380 | class xmlrpc_client { |
---|
381 | var $path; |
---|
382 | var $server; |
---|
383 | var $port; |
---|
384 | var $errno; |
---|
385 | var $errstring; |
---|
386 | var $debug=0; |
---|
387 | var $username=""; |
---|
388 | var $password=""; |
---|
389 | var $cert=""; |
---|
390 | var $certpass=""; |
---|
391 | |
---|
392 | function xmlrpc_client($path, $server, $port=0) { |
---|
393 | $this->port=$port; $this->server=$server; $this->path=$path; |
---|
394 | } |
---|
395 | |
---|
396 | function setDebug($in) { |
---|
397 | if ($in) { |
---|
398 | $this->debug=1; |
---|
399 | } else { |
---|
400 | $this->debug=0; |
---|
401 | } |
---|
402 | } |
---|
403 | |
---|
404 | function setCredentials($u, $p) { |
---|
405 | $this->username=$u; |
---|
406 | $this->password=$p; |
---|
407 | } |
---|
408 | |
---|
409 | function setCertificate($cert, $certpass) { |
---|
410 | $this->cert = $cert; |
---|
411 | $this->certpass = $certpass; |
---|
412 | } |
---|
413 | |
---|
414 | function send($msg, $timeout=0, $method='http') { |
---|
415 | // where msg is an xmlrpcmsg |
---|
416 | $msg->debug=$this->debug; |
---|
417 | |
---|
418 | if ($method == 'https') { |
---|
419 | return $this->sendPayloadHTTPS($msg, |
---|
420 | $this->server, |
---|
421 | $this->port, $timeout, |
---|
422 | $this->username, $this->password, |
---|
423 | $this->cert, |
---|
424 | $this->certpass); |
---|
425 | } else { |
---|
426 | return $this->sendPayloadHTTP10($msg, $this->server, $this->port, |
---|
427 | $timeout, $this->username, |
---|
428 | $this->password); |
---|
429 | } |
---|
430 | } |
---|
431 | |
---|
432 | function sendPayloadHTTP10($msg, $server, $port, $timeout=0, |
---|
433 | $username="", $password="") { |
---|
434 | if ($port==0) $port=80; |
---|
435 | if($timeout>0) |
---|
436 | $fp=@fsockopen($server, $port, |
---|
437 | $this->errno, $this->errstr, $timeout); |
---|
438 | # $fp=@fsockopen($server, $port, |
---|
439 | # &$this->errno, &$this->errstr, $timeout); |
---|
440 | else |
---|
441 | $fp=@fsockopen($server, $port, |
---|
442 | $this->errno, $this->errstr); |
---|
443 | # $fp=@fsockopen($server, $port, |
---|
444 | # &$this->errno, &$this->errstr); |
---|
445 | if (!$fp) { |
---|
446 | return 0; |
---|
447 | } |
---|
448 | // Only create the payload if it was not created previously |
---|
449 | if(empty($msg->payload)) $msg->createPayload(); |
---|
450 | |
---|
451 | // thanks to Grant Rauscher <[email protected]> |
---|
452 | // for this |
---|
453 | $credentials=""; |
---|
454 | if ($username!="") { |
---|
455 | $credentials="Authorization: Basic " . |
---|
456 | base64_encode($username . ":" . $password) . "\r\n"; |
---|
457 | } |
---|
458 | |
---|
459 | $op= "POST " . $this->path. " HTTP/1.0\r\nUser-Agent: PHP XMLRPC 1.0\r\n" . |
---|
460 | "Host: ". $this->server . "\r\n" . |
---|
461 | $credentials . |
---|
462 | "Content-Type: text/xml\r\nContent-Length: " . |
---|
463 | strlen($msg->payload) . "\r\n\r\n" . |
---|
464 | $msg->payload; |
---|
465 | |
---|
466 | if (!fputs($fp, $op, strlen($op))) { |
---|
467 | $this->errstr="Write error"; |
---|
468 | return 0; |
---|
469 | } |
---|
470 | $resp=$msg->parseResponseFile($fp); |
---|
471 | fclose($fp); |
---|
472 | return $resp; |
---|
473 | } |
---|
474 | |
---|
475 | // contributed by Justin Miller <[email protected]> |
---|
476 | // requires curl to be built into PHP |
---|
477 | function sendPayloadHTTPS($msg, $server, $port, $timeout=0, |
---|
478 | $username="", $password="", $cert="", |
---|
479 | $certpass="") { |
---|
480 | global $xmlrpcerr, $xmlrpcstr; |
---|
481 | if ($port == 0) $port = 443; |
---|
482 | |
---|
483 | // Only create the payload if it was not created previously |
---|
484 | if(empty($msg->payload)) $msg->createPayload(); |
---|
485 | |
---|
486 | if (!function_exists("curl_init")) { |
---|
487 | $r=new xmlrpcresp(0, $xmlrpcerr["no_ssl"], |
---|
488 | $xmlrpcstr["no_ssl"]); |
---|
489 | return $r; |
---|
490 | } |
---|
491 | |
---|
492 | $curl = curl_init("https://" . $server . ':' . $port . |
---|
493 | $this->path); |
---|
494 | |
---|
495 | curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); |
---|
496 | // results into variable |
---|
497 | if ($this->debug) { |
---|
498 | curl_setopt($curl, CURLOPT_VERBOSE, 1); |
---|
499 | } |
---|
500 | curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC 1.0'); |
---|
501 | // required for XMLRPC |
---|
502 | curl_setopt($curl, CURLOPT_POST, 1); |
---|
503 | // post the data |
---|
504 | curl_setopt($curl, CURLOPT_POSTFIELDS, $msg->payload); |
---|
505 | // the data |
---|
506 | curl_setopt($curl, CURLOPT_HEADER, 1); |
---|
507 | // return the header too |
---|
508 | curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml')); |
---|
509 | // required for XMLRPC |
---|
510 | if ($timeout) curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : |
---|
511 | $timeout - 1); |
---|
512 | // timeout is borked |
---|
513 | if ($username && $password) curl_setopt($curl, CURLOPT_USERPWD, |
---|
514 | "$username:$password"); |
---|
515 | // set auth stuff |
---|
516 | if ($cert) curl_setopt($curl, CURLOPT_SSLCERT, $cert); |
---|
517 | // set cert file |
---|
518 | if ($certpass) curl_setopt($curl, CURLOPT_SSLCERTPASSWD, |
---|
519 | $certpass); |
---|
520 | // set cert password |
---|
521 | |
---|
522 | $result = curl_exec($curl); |
---|
523 | |
---|
524 | if (!$result) { |
---|
525 | $resp=new xmlrpcresp(0, |
---|
526 | $xmlrpcerr["curl_fail"], |
---|
527 | $xmlrpcstr["curl_fail"]. ": ". |
---|
528 | curl_error($curl)); |
---|
529 | } else { |
---|
530 | $resp = $msg->parseResponse($result); |
---|
531 | } |
---|
532 | curl_close($curl); |
---|
533 | return $resp; |
---|
534 | } |
---|
535 | |
---|
536 | } // end class xmlrpc_client |
---|
537 | |
---|
538 | class xmlrpcresp { |
---|
539 | var $xv; |
---|
540 | var $fn; |
---|
541 | var $fs; |
---|
542 | var $hdrs; |
---|
543 | |
---|
544 | function xmlrpcresp($val, $fcode=0, $fstr="") { |
---|
545 | if ($fcode!=0) { |
---|
546 | $this->xv=0; |
---|
547 | $this->fn=$fcode; |
---|
548 | $this->fs=trim(htmlspecialchars($fstr)); |
---|
549 | logIO("O",$this->fs); |
---|
550 | } else { |
---|
551 | $this->xv=$val; |
---|
552 | $this->fn=0; |
---|
553 | } |
---|
554 | } |
---|
555 | |
---|
556 | function faultCode() { |
---|
557 | if (isset($this->fn)) |
---|
558 | return $this->fn; |
---|
559 | else |
---|
560 | return 0; |
---|
561 | } |
---|
562 | |
---|
563 | function faultString() { return $this->fs; } |
---|
564 | function value() { return $this->xv; } |
---|
565 | |
---|
566 | function serialize() { |
---|
567 | $rs="<methodResponse>"; |
---|
568 | if ($this->fn) { |
---|
569 | $rs.="<fault> |
---|
570 | <value> |
---|
571 | <struct> |
---|
572 | <member> |
---|
573 | <name>faultCode</name> |
---|
574 | <value><int>" . $this->fn . "</int></value> |
---|
575 | </member> |
---|
576 | <member> |
---|
577 | <name>faultString</name> |
---|
578 | <value><string>" . $this->fs . "</string></value> |
---|
579 | </member> |
---|
580 | </struct> |
---|
581 | </value> |
---|
582 | </fault>"; |
---|
583 | } else { |
---|
584 | $rs.="<params><param>" . $this->xv->serialize() . |
---|
585 | "</param></params>"; |
---|
586 | } |
---|
587 | $rs.="</methodResponse>"; |
---|
588 | |
---|
589 | /* begin Logging |
---|
590 | $f=fopen("xmlrpc/xmlrpc.log","a+"); |
---|
591 | fwrite($f, date("Ymd H:i:s")."\n\nResponse:\n\n".$rs); |
---|
592 | fclose($f); |
---|
593 | end Logging */ |
---|
594 | logIO("O",$rs); |
---|
595 | |
---|
596 | return $rs; |
---|
597 | } |
---|
598 | } |
---|
599 | |
---|
600 | class xmlrpcmsg { |
---|
601 | var $payload; |
---|
602 | var $methodname; |
---|
603 | var $params=array(); |
---|
604 | var $debug=0; |
---|
605 | |
---|
606 | function xmlrpcmsg($meth, $pars=0) { |
---|
607 | $this->methodname=$meth; |
---|
608 | if (is_array($pars) && sizeof($pars)>0) { |
---|
609 | for($i=0; $i<sizeof($pars); $i++) |
---|
610 | $this->addParam($pars[$i]); |
---|
611 | } |
---|
612 | } |
---|
613 | |
---|
614 | function xml_header() { |
---|
615 | /* commenting this out until we get further testing... |
---|
616 | if (function_exists('get_settings')) { |
---|
617 | $encoding = ' encoding="'.get_settings('blog_charset').'"'; |
---|
618 | } else { |
---|
619 | $encoding = ''; |
---|
620 | } |
---|
621 | */ |
---|
622 | $encoding = ''; |
---|
623 | return "<?xml version=\"1.0\"$encoding?".">\n<methodCall>\n"; |
---|
624 | } |
---|
625 | |
---|
626 | function xml_footer() { |
---|
627 | return "</methodCall>\n"; |
---|
628 | } |
---|
629 | |
---|
630 | function createPayload() { |
---|
631 | $this->payload=$this->xml_header(); |
---|
632 | $this->payload.="<methodName>" . $this->methodname . "</methodName>\n"; |
---|
633 | // if (sizeof($this->params)) { |
---|
634 | $this->payload.="<params>\n"; |
---|
635 | for($i=0; $i<sizeof($this->params); $i++) { |
---|
636 | $p=$this->params[$i]; |
---|
637 | $this->payload.="<param>\n" . $p->serialize() . |
---|
638 | "</param>\n"; |
---|
639 | } |
---|
640 | $this->payload.="</params>\n"; |
---|
641 | // } |
---|
642 | $this->payload.=$this->xml_footer(); |
---|
643 | $this->payload=str_replace("\n", "\r\n", $this->payload); |
---|
644 | } |
---|
645 | |
---|
646 | function method($meth="") { |
---|
647 | if ($meth!="") { |
---|
648 | $this->methodname=$meth; |
---|
649 | } |
---|
650 | return $this->methodname; |
---|
651 | } |
---|
652 | |
---|
653 | function serialize() { |
---|
654 | $this->createPayload(); |
---|
655 | logIO("O",$this->payload); |
---|
656 | return $this->payload; |
---|
657 | } |
---|
658 | |
---|
659 | function addParam($par) { $this->params[]=$par; } |
---|
660 | function getParam($i) { return $this->params[$i]; } |
---|
661 | function getNumParams() { return sizeof($this->params); } |
---|
662 | |
---|
663 | function parseResponseFile($fp) { |
---|
664 | $ipd=""; |
---|
665 | |
---|
666 | while($data=fread($fp, 32768)) { |
---|
667 | $ipd.=$data; |
---|
668 | } |
---|
669 | return $this->parseResponse($ipd); |
---|
670 | } |
---|
671 | |
---|
672 | function parseResponse($data="") { |
---|
673 | global $_xh,$xmlrpcerr,$xmlrpcstr; |
---|
674 | global $xmlrpc_defencoding; |
---|
675 | |
---|
676 | |
---|
677 | $parser = xml_parser_create($xmlrpc_defencoding); |
---|
678 | |
---|
679 | $_xh[$parser]=array(); |
---|
680 | |
---|
681 | $_xh[$parser]['st']=""; |
---|
682 | $_xh[$parser]['cm']=0; |
---|
683 | $_xh[$parser]['isf']=0; |
---|
684 | $_xh[$parser]['ac']=""; |
---|
685 | $_xh[$parser]['qt']=""; |
---|
686 | $_xh[$parser]['ha']=""; |
---|
687 | $_xh[$parser]['ac']=""; |
---|
688 | |
---|
689 | xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); |
---|
690 | xml_set_element_handler($parser, "xmlrpc_se", "xmlrpc_ee"); |
---|
691 | xml_set_character_data_handler($parser, "xmlrpc_cd"); |
---|
692 | xml_set_default_handler($parser, "xmlrpc_dh"); |
---|
693 | $xmlrpc_value=new xmlrpcval; |
---|
694 | |
---|
695 | if ($this->debug) |
---|
696 | print "<PRE>---GOT---\n" . htmlspecialchars($data) . |
---|
697 | "\n---END---\n</PRE>"; |
---|
698 | if ($data=="") { |
---|
699 | error_log("No response received from server."); |
---|
700 | $r=new xmlrpcresp(0, $xmlrpcerr["no_data"], |
---|
701 | $xmlrpcstr["no_data"]); |
---|
702 | xml_parser_free($parser); |
---|
703 | return $r; |
---|
704 | } |
---|
705 | // see if we got an HTTP 200 OK, else bomb |
---|
706 | // but only do this if we're using the HTTP protocol. |
---|
707 | if (ereg("^HTTP",$data) && |
---|
708 | !ereg("^HTTP/[0-9\.]+ 200 ", $data)) { |
---|
709 | $errstr= substr($data, 0, strpos($data, "\n")-1); |
---|
710 | error_log("HTTP error, got response: " .$errstr); |
---|
711 | $r=new xmlrpcresp(0, $xmlrpcerr["http_error"], |
---|
712 | $xmlrpcstr["http_error"]. " (" . $errstr . ")"); |
---|
713 | xml_parser_free($parser); |
---|
714 | return $r; |
---|
715 | } |
---|
716 | |
---|
717 | // if using HTTP, then gotta get rid of HTTP headers here |
---|
718 | // and we store them in the 'ha' bit of our data array |
---|
719 | if (ereg("^HTTP", $data)) { |
---|
720 | $ar=explode("\r\n", $data); |
---|
721 | $newdata=""; |
---|
722 | $hdrfnd=0; |
---|
723 | for ($i=0; $i<sizeof($ar); $i++) { |
---|
724 | if (!$hdrfnd) { |
---|
725 | if (strlen($ar[$i])>0) { |
---|
726 | $_xh[$parser]['ha'].=$ar[$i]. "\r\n"; |
---|
727 | } else { |
---|
728 | $hdrfnd=1; |
---|
729 | } |
---|
730 | } else { |
---|
731 | $newdata.=$ar[$i] . "\r\n"; |
---|
732 | } |
---|
733 | } |
---|
734 | $data=$newdata; |
---|
735 | } |
---|
736 | |
---|
737 | if (!xml_parse($parser, $data, sizeof($data))) { |
---|
738 | // thanks to Peter Kocks <[email protected]> |
---|
739 | if((xml_get_current_line_number($parser)) == 1) |
---|
740 | $errstr = "XML error at line 1, check URL"; |
---|
741 | else |
---|
742 | $errstr = sprintf("XML error: %s at line %d", |
---|
743 | xml_error_string(xml_get_error_code($parser)), |
---|
744 | xml_get_current_line_number($parser)); |
---|
745 | error_log($errstr); |
---|
746 | $r=new xmlrpcresp(0, $xmlrpcerr["invalid_return"], |
---|
747 | $xmlrpcstr["invalid_return"]); |
---|
748 | xml_parser_free($parser); |
---|
749 | return $r; |
---|
750 | } |
---|
751 | xml_parser_free($parser); |
---|
752 | if ($this->debug) { |
---|
753 | print "<PRE>---EVALING---[" . |
---|
754 | strlen($_xh[$parser]['st']) . " chars]---\n" . |
---|
755 | htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>"; |
---|
756 | } |
---|
757 | if (strlen($_xh[$parser]['st'])==0) { |
---|
758 | // then something odd has happened |
---|
759 | // and it's time to generate a client side error |
---|
760 | // indicating something odd went on |
---|
761 | $r=new xmlrpcresp(0, $xmlrpcerr["invalid_return"], |
---|
762 | $xmlrpcstr["invalid_return"]); |
---|
763 | } else { |
---|
764 | eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); |
---|
765 | if ($_xh[$parser]['isf']) { |
---|
766 | $f=$v->structmem("faultCode"); |
---|
767 | $fs=$v->structmem("faultString"); |
---|
768 | $r=new xmlrpcresp($v, |
---|
769 | $f->scalarval(), |
---|
770 | $fs->scalarval()); |
---|
771 | } else { |
---|
772 | $r=new xmlrpcresp($v); |
---|
773 | } |
---|
774 | } |
---|
775 | $r->hdrs=split("\r?\n", $_xh[$parser]['ha']); |
---|
776 | return $r; |
---|
777 | } |
---|
778 | |
---|
779 | } |
---|
780 | |
---|
781 | class xmlrpcval { |
---|
782 | var $me=array(); |
---|
783 | var $mytype=0; |
---|
784 | |
---|
785 | function xmlrpcval($val=-1, $type="") { |
---|
786 | global $xmlrpcTypes; |
---|
787 | // but this doesn't work, so we redefine it. WEIRD BUG ALERT |
---|
788 | $xmlrpcI4="i4"; |
---|
789 | $xmlrpcInt="int"; |
---|
790 | $xmlrpcBoolean="boolean"; |
---|
791 | $xmlrpcDouble="double"; |
---|
792 | $xmlrpcString="string"; |
---|
793 | $xmlrpcDateTime="dateTime.iso8601"; |
---|
794 | $xmlrpcBase64="base64"; |
---|
795 | $xmlrpcArray="array"; |
---|
796 | $xmlrpcStruct="struct"; |
---|
797 | $xmlrpcTypes=array($xmlrpcI4 => 1, |
---|
798 | $xmlrpcInt => 1, |
---|
799 | $xmlrpcBoolean => 1, |
---|
800 | $xmlrpcString => 1, |
---|
801 | $xmlrpcDouble => 1, |
---|
802 | $xmlrpcDateTime => 1, |
---|
803 | $xmlrpcBase64 => 1, |
---|
804 | $xmlrpcArray => 2, |
---|
805 | $xmlrpcStruct => 3); |
---|
806 | // print_r($xmlrpcTypes); |
---|
807 | $this->me=array(); |
---|
808 | $this->mytype=0; |
---|
809 | if ($val!=-1 || $type!="") { |
---|
810 | if ($type=="") $type="string"; |
---|
811 | if ($xmlrpcTypes[$type]==1) { |
---|
812 | $this->addScalar($val,$type); |
---|
813 | } |
---|
814 | else if ($xmlrpcTypes[$type]==2) |
---|
815 | $this->addArray($val); |
---|
816 | else if ($xmlrpcTypes[$type]==3) |
---|
817 | $this->addStruct($val); |
---|
818 | } |
---|
819 | } |
---|
820 | |
---|
821 | function addScalar($val, $type="string") { |
---|
822 | global $xmlrpcTypes, $xmlrpcBoolean; |
---|
823 | |
---|
824 | if ($this->mytype==1) { |
---|
825 | echo "<B>xmlrpcval</B>: scalar can have only one value<BR>"; |
---|
826 | return 0; |
---|
827 | } |
---|
828 | $typeof=$xmlrpcTypes[$type]; |
---|
829 | if ($typeof!=1) { |
---|
830 | echo "<B>xmlrpcval</B>: not a scalar type (${typeof})<BR>"; |
---|
831 | return 0; |
---|
832 | } |
---|
833 | |
---|
834 | if ($type==$xmlrpcBoolean) { |
---|
835 | if (strcasecmp($val,"true")==0 || |
---|
836 | $val==1 || ($val==true && |
---|
837 | strcasecmp($val,"false"))) { |
---|
838 | $val=1; |
---|
839 | } else { |
---|
840 | $val=0; |
---|
841 | } |
---|
842 | } |
---|
843 | |
---|
844 | if ($this->mytype==2) { |
---|
845 | // we're adding to an array here |
---|
846 | $ar=$this->me["array"]; |
---|
847 | $ar[]=new xmlrpcval($val, $type); |
---|
848 | $this->me["array"]=$ar; |
---|
849 | } else { |
---|
850 | // a scalar, so set the value and remember we're scalar |
---|
851 | $this->me[$type]=$val; |
---|
852 | $this->mytype=$typeof; |
---|
853 | } |
---|
854 | return 1; |
---|
855 | } |
---|
856 | |
---|
857 | function addArray($vals) { |
---|
858 | global $xmlrpcTypes; |
---|
859 | if ($this->mytype!=0) { |
---|
860 | echo "<B>xmlrpcval</B>: already initialized as a [" . |
---|
861 | $this->kindOf() . "]<BR>"; |
---|
862 | return 0; |
---|
863 | } |
---|
864 | |
---|
865 | $this->mytype=$xmlrpcTypes["array"]; |
---|
866 | $this->me["array"]=$vals; |
---|
867 | return 1; |
---|
868 | } |
---|
869 | |
---|
870 | function addStruct($vals) { |
---|
871 | global $xmlrpcTypes; |
---|
872 | if ($this->mytype!=0) { |
---|
873 | echo "<B>xmlrpcval</B>: already initialized as a [" . |
---|
874 | $this->kindOf() . "]<BR>"; |
---|
875 | return 0; |
---|
876 | } |
---|
877 | $this->mytype=$xmlrpcTypes["struct"]; |
---|
878 | $this->me["struct"]=$vals; |
---|
879 | return 1; |
---|
880 | } |
---|
881 | |
---|
882 | function dump($ar) { |
---|
883 | reset($ar); |
---|
884 | while ( list( $key, $val ) = each( $ar ) ) { |
---|
885 | echo "$key => $val<br>"; |
---|
886 | if ($key == 'array') |
---|
887 | while ( list( $key2, $val2 ) = each( $val ) ) { |
---|
888 | echo "-- $key2 => $val2<br>"; |
---|
889 | } |
---|
890 | } |
---|
891 | } |
---|
892 | |
---|
893 | function kindOf() { |
---|
894 | switch($this->mytype) { |
---|
895 | case 3: |
---|
896 | return "struct"; |
---|
897 | break; |
---|
898 | case 2: |
---|
899 | return "array"; |
---|
900 | break; |
---|
901 | case 1: |
---|
902 | return "scalar"; |
---|
903 | break; |
---|
904 | default: |
---|
905 | return "undef"; |
---|
906 | } |
---|
907 | } |
---|
908 | |
---|
909 | function serializedata($typ, $val) { |
---|
910 | $rs=""; |
---|
911 | global $xmlrpcTypes, $xmlrpcBase64, $xmlrpcString, |
---|
912 | $xmlrpcBoolean; |
---|
913 | switch($xmlrpcTypes[$typ]) { |
---|
914 | case 3: |
---|
915 | // struct |
---|
916 | $rs.="<struct>\n"; |
---|
917 | reset($val); |
---|
918 | while(list($key2, $val2)=each($val)) { |
---|
919 | $rs.="<member><name>${key2}</name>\n"; |
---|
920 | $rs.=$this->serializeval($val2); |
---|
921 | $rs.="</member>\n"; |
---|
922 | } |
---|
923 | $rs.="</struct>"; |
---|
924 | break; |
---|
925 | case 2: |
---|
926 | // array |
---|
927 | $rs.="<array>\n<data>\n"; |
---|
928 | for($i=0; $i<sizeof($val); $i++) { |
---|
929 | $rs.=$this->serializeval($val[$i]); |
---|
930 | } |
---|
931 | $rs.="</data>\n</array>"; |
---|
932 | break; |
---|
933 | case 1: |
---|
934 | switch ($typ) { |
---|
935 | case $xmlrpcBase64: |
---|
936 | $rs.="<${typ}>" . base64_encode($val) . "</${typ}>"; |
---|
937 | break; |
---|
938 | case $xmlrpcBoolean: |
---|
939 | $rs.="<${typ}>" . ($val ? "1" : "0") . "</${typ}>"; |
---|
940 | break; |
---|
941 | case $xmlrpcString: |
---|
942 | $rs.="<${typ}>" . htmlspecialchars($val). "</${typ}>"; |
---|
943 | break; |
---|
944 | default: |
---|
945 | $rs.="<${typ}>${val}</${typ}>"; |
---|
946 | } |
---|
947 | break; |
---|
948 | default: |
---|
949 | break; |
---|
950 | } |
---|
951 | return $rs; |
---|
952 | } |
---|
953 | |
---|
954 | function serialize() { |
---|
955 | return $this->serializeval($this); |
---|
956 | } |
---|
957 | |
---|
958 | function serializeval($o) { |
---|
959 | global $xmlrpcTypes; |
---|
960 | $rs=""; |
---|
961 | $ar=$o->me; |
---|
962 | reset($ar); |
---|
963 | list($typ, $val) = each($ar); |
---|
964 | $rs.="<value>"; |
---|
965 | $rs.=$this->serializedata($typ, $val); |
---|
966 | $rs.="</value>\n"; |
---|
967 | return $rs; |
---|
968 | } |
---|
969 | |
---|
970 | function structmem($m) { |
---|
971 | $nv=$this->me["struct"][$m]; |
---|
972 | return $nv; |
---|
973 | } |
---|
974 | |
---|
975 | function structreset() { |
---|
976 | reset($this->me["struct"]); |
---|
977 | } |
---|
978 | |
---|
979 | function structeach() { |
---|
980 | return each($this->me["struct"]); |
---|
981 | } |
---|
982 | |
---|
983 | function getval() { |
---|
984 | // UNSTABLE |
---|
985 | global $xmlrpcBoolean, $xmlrpcBase64; |
---|
986 | reset($this->me); |
---|
987 | list($a,$b)=each($this->me); |
---|
988 | // contributed by I Sofer, 2001-03-24 |
---|
989 | // add support for nested arrays to scalarval |
---|
990 | // i've created a new method here, so as to |
---|
991 | // preserve back compatibility |
---|
992 | |
---|
993 | if (is_array($b)) { |
---|
994 | foreach ($b as $id => $cont) { |
---|
995 | $b[$id] = $cont->scalarval(); |
---|
996 | } |
---|
997 | } |
---|
998 | |
---|
999 | // add support for structures directly encoding php objects |
---|
1000 | if (is_object($b)) { |
---|
1001 | $t = get_object_vars($b); |
---|
1002 | foreach ($t as $id => $cont) { |
---|
1003 | $t[$id] = $cont->scalarval(); |
---|
1004 | } |
---|
1005 | foreach ($t as $id => $cont) { |
---|
1006 | eval('$b->'.$id.' = $cont;'); |
---|
1007 | } |
---|
1008 | } |
---|
1009 | // end contrib |
---|
1010 | return $b; |
---|
1011 | } |
---|
1012 | |
---|
1013 | function scalarval() { |
---|
1014 | global $xmlrpcBoolean, $xmlrpcBase64; |
---|
1015 | reset($this->me); |
---|
1016 | list($a,$b)=each($this->me); |
---|
1017 | return $b; |
---|
1018 | } |
---|
1019 | |
---|
1020 | function scalartyp() { |
---|
1021 | global $xmlrpcI4, $xmlrpcInt; |
---|
1022 | reset($this->me); |
---|
1023 | list($a,$b)=each($this->me); |
---|
1024 | if ($a==$xmlrpcI4) |
---|
1025 | $a=$xmlrpcInt; |
---|
1026 | return $a; |
---|
1027 | } |
---|
1028 | |
---|
1029 | function arraymem($m) { |
---|
1030 | $nv=$this->me["array"][$m]; |
---|
1031 | return $nv; |
---|
1032 | } |
---|
1033 | |
---|
1034 | function arraysize() { |
---|
1035 | reset($this->me); |
---|
1036 | list($a,$b)=each($this->me); |
---|
1037 | return sizeof($b); |
---|
1038 | } |
---|
1039 | } |
---|
1040 | |
---|
1041 | // date helpers |
---|
1042 | function iso8601_encode($timet, $utc=0) { |
---|
1043 | // return an ISO8601 encoded string |
---|
1044 | // really, timezones ought to be supported |
---|
1045 | // but the XML-RPC spec says: |
---|
1046 | // |
---|
1047 | // "Don't assume a timezone. It should be specified by the server in its |
---|
1048 | // documentation what assumptions it makes about timezones." |
---|
1049 | // |
---|
1050 | // these routines always assume localtime unless |
---|
1051 | // $utc is set to 1, in which case UTC is assumed |
---|
1052 | // and an adjustment for locale is made when encoding |
---|
1053 | if (!$utc) { |
---|
1054 | $t=strftime("%Y%m%dT%H:%M:%S", $timet); |
---|
1055 | } else { |
---|
1056 | if (function_exists("gmstrftime")) |
---|
1057 | // gmstrftime doesn't exist in some versions |
---|
1058 | // of PHP |
---|
1059 | $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet); |
---|
1060 | else { |
---|
1061 | $t=strftime("%Y%m%dT%H:%M:%S", $timet-date("Z")); |
---|
1062 | } |
---|
1063 | } |
---|
1064 | return $t; |
---|
1065 | } |
---|
1066 | |
---|
1067 | function iso8601_decode($idate, $utc=0) { |
---|
1068 | // return a timet in the localtime, or UTC |
---|
1069 | $t=0; |
---|
1070 | if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", |
---|
1071 | $idate, $regs)) { |
---|
1072 | if ($utc) { |
---|
1073 | $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); |
---|
1074 | } else { |
---|
1075 | $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); |
---|
1076 | } |
---|
1077 | } |
---|
1078 | return $t; |
---|
1079 | } |
---|
1080 | |
---|
1081 | /**************************************************************** |
---|
1082 | * xmlrpc_decode takes a message in PHP xmlrpc object format and * |
---|
1083 | * tranlates it into native PHP types. * |
---|
1084 | * * |
---|
1085 | * author: Dan Libby ([email protected]) * |
---|
1086 | ****************************************************************/ |
---|
1087 | if (!function_exists('phpxmlrpc_decode')) { |
---|
1088 | function phpxmlrpc_decode($xmlrpc_val) { |
---|
1089 | $kind = @$xmlrpc_val->kindOf(); |
---|
1090 | |
---|
1091 | if($kind == "scalar") { |
---|
1092 | return $xmlrpc_val->scalarval(); |
---|
1093 | } |
---|
1094 | else if($kind == "array") { |
---|
1095 | $size = $xmlrpc_val->arraysize(); |
---|
1096 | $arr = array(); |
---|
1097 | |
---|
1098 | for($i = 0; $i < $size; $i++) { |
---|
1099 | $arr[]=phpxmlrpc_decode($xmlrpc_val->arraymem($i)); |
---|
1100 | } |
---|
1101 | return $arr; |
---|
1102 | } |
---|
1103 | else if($kind == "struct") { |
---|
1104 | $xmlrpc_val->structreset(); |
---|
1105 | $arr = array(); |
---|
1106 | |
---|
1107 | while(list($key,$value)=$xmlrpc_val->structeach()) { |
---|
1108 | $arr[$key] = phpxmlrpc_decode($value); |
---|
1109 | } |
---|
1110 | return $arr; |
---|
1111 | } |
---|
1112 | } |
---|
1113 | } |
---|
1114 | |
---|
1115 | /**************************************************************** |
---|
1116 | * xmlrpc_encode takes native php types and encodes them into * |
---|
1117 | * xmlrpc PHP object format. * |
---|
1118 | * BUG: All sequential arrays are turned into structs. I don't * |
---|
1119 | * know of a good way to determine if an array is sequential * |
---|
1120 | * only. * |
---|
1121 | * * |
---|
1122 | * feature creep -- could support more types via optional type * |
---|
1123 | * argument. * |
---|
1124 | * * |
---|
1125 | * author: Dan Libby ([email protected]) * |
---|
1126 | ****************************************************************/ |
---|
1127 | if (!function_exists('phpxmlrpc_encode')) { |
---|
1128 | function phpxmlrpc_encode($php_val) { |
---|
1129 | global $xmlrpcInt; |
---|
1130 | global $xmlrpcDouble; |
---|
1131 | global $xmlrpcString; |
---|
1132 | global $xmlrpcArray; |
---|
1133 | global $xmlrpcStruct; |
---|
1134 | global $xmlrpcBoolean; |
---|
1135 | |
---|
1136 | $type = gettype($php_val); |
---|
1137 | $xmlrpc_val = new xmlrpcval; |
---|
1138 | |
---|
1139 | switch($type) { |
---|
1140 | case "array": |
---|
1141 | case "object": |
---|
1142 | $arr = array(); |
---|
1143 | while (list($k,$v) = each($php_val)) { |
---|
1144 | $arr[$k] = phpxmlrpc_encode($v); |
---|
1145 | } |
---|
1146 | $xmlrpc_val->addStruct($arr); |
---|
1147 | break; |
---|
1148 | case "integer": |
---|
1149 | $xmlrpc_val->addScalar($php_val, $xmlrpcInt); |
---|
1150 | break; |
---|
1151 | case "double": |
---|
1152 | $xmlrpc_val->addScalar($php_val, $xmlrpcDouble); |
---|
1153 | break; |
---|
1154 | case "string": |
---|
1155 | $xmlrpc_val->addScalar($php_val, $xmlrpcString); |
---|
1156 | break; |
---|
1157 | // <G_Giunta_2001-02-29> |
---|
1158 | // Add support for encoding/decoding of booleans, since they are supported in PHP |
---|
1159 | case "boolean": |
---|
1160 | $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean); |
---|
1161 | break; |
---|
1162 | // </G_Giunta_2001-02-29> |
---|
1163 | case "unknown type": |
---|
1164 | default: |
---|
1165 | // giancarlo pinerolo <[email protected]> |
---|
1166 | // it has to return |
---|
1167 | // an empty object in case (which is already |
---|
1168 | // at this point), not a boolean. |
---|
1169 | break; |
---|
1170 | } |
---|
1171 | return $xmlrpc_val; |
---|
1172 | } |
---|
1173 | } |
---|
1174 | |
---|
1175 | |
---|
1176 | |
---|
1177 | } |
---|
1178 | ?> |
---|