OSDN Git Service

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