OSDN Git Service

XML-RPC for PHP Unspecified PHP Code Execution Vulnerability
[nucleus-jp/nucleus-jp-ancient.git] / utf8 / nucleus / libs / xmlrpc.inc.php
1 <?php                                   // -*-c++-*-\r
2 // by Edd Dumbill (C) 1999-2002\r
3 // <edd@usefulinc.com>\r
4 // $Id: xmlrpc.inc.php,v 1.5 2005-08-13 07:24:44 kimitake Exp $\r
5 // $NucleusJP$\r
6 \r
7 \r
8 // Copyright (c) 1999,2000,2002 Edd Dumbill.\r
9 // All rights reserved.\r
10 //\r
11 // Redistribution and use in source and binary forms, with or without\r
12 // modification, are permitted provided that the following conditions\r
13 // are met:\r
14 //\r
15 //    * Redistributions of source code must retain the above copyright\r
16 //      notice, this list of conditions and the following disclaimer.\r
17 //\r
18 //    * Redistributions in binary form must reproduce the above\r
19 //      copyright notice, this list of conditions and the following\r
20 //      disclaimer in the documentation and/or other materials provided\r
21 //      with the distribution.\r
22 //\r
23 //    * Neither the name of the "XML-RPC for PHP" nor the names of its\r
24 //      contributors may be used to endorse or promote products derived\r
25 //      from this software without specific prior written permission.\r
26 //\r
27 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
28 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
29 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
30 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
31 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
32 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
33 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
34 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
35 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
36 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
37 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\r
38 // OF THE POSSIBILITY OF SUCH DAMAGE.\r
39 \r
40         if (!function_exists('xml_parser_create'))\r
41         {\r
42                 // Win 32 fix. From: 'Leo West' <lwest@imaginet.fr>\r
43                 if($WINDIR)\r
44                 {\r
45                         dl('php3_xml.dll');\r
46                 }\r
47                 else\r
48                 {\r
49                         dl('xml.so');\r
50                 }\r
51         }\r
52 \r
53         // G. Giunta 2005/01/29: declare global these variables,\r
54         // so that xmlrpc.inc will work even if included from within a function\r
55         // NB: it will give warnings in PHP3, so we comment it out\r
56         // Milosch: Next round, maybe we should explicitly request these via $GLOBALS where used.\r
57         if (phpversion() >= '4')\r
58         {\r
59                 global $xmlrpcI4;\r
60                 global $xmlrpcInt;\r
61                 global $xmlrpcDouble;\r
62                 global $xmlrpcString;\r
63                 global $xmlrpcDateTime;\r
64                 global $xmlrpcBase64;\r
65                 global $xmlrpcArray;\r
66                 global $xmlrpcStruct;\r
67 \r
68                 global $xmlrpcTypes;\r
69                 global $xmlEntities;\r
70                 global $xmlrpcerr;\r
71                 global $xmlrpcstr;\r
72                 global $xmlrpc_defencoding;\r
73                 global $xmlrpc_internalencoding;\r
74                 global $xmlrpcName;\r
75                 global $xmlrpcVersion;\r
76                 global $xmlrpcerruser;\r
77                 global $xmlrpcerrxml;\r
78                 global $xmlrpc_backslash;\r
79                 global $_xh;\r
80         }\r
81         $xmlrpcI4='i4';\r
82         $xmlrpcInt='int';\r
83         $xmlrpcBoolean='boolean';\r
84         $xmlrpcDouble='double';\r
85         $xmlrpcString='string';\r
86         $xmlrpcDateTime='dateTime.iso8601';\r
87         $xmlrpcBase64='base64';\r
88         $xmlrpcArray='array';\r
89         $xmlrpcStruct='struct';\r
90 \r
91         $xmlrpcTypes=array(\r
92                 $xmlrpcI4       => 1,\r
93                 $xmlrpcInt      => 1,\r
94                 $xmlrpcBoolean  => 1,\r
95                 $xmlrpcString   => 1,\r
96                 $xmlrpcDouble   => 1,\r
97                 $xmlrpcDateTime => 1,\r
98                 $xmlrpcBase64   => 1,\r
99                 $xmlrpcArray    => 2,\r
100                 $xmlrpcStruct   => 3\r
101         );\r
102 \r
103         $xmlEntities=array(\r
104                 'amp'  => '&',\r
105                 'quot' => '"',\r
106                 'lt'   => '<',\r
107                 'gt'   => '>',\r
108                 'apos' => "'"\r
109         );\r
110 \r
111         $xmlrpcerr['unknown_method']=1;\r
112         $xmlrpcstr['unknown_method']='Unknown method';\r
113         $xmlrpcerr['invalid_return']=2;\r
114         $xmlrpcstr['invalid_return']='Invalid return payload: enable debugging to examine incoming payload';\r
115         $xmlrpcerr['incorrect_params']=3;\r
116         $xmlrpcstr['incorrect_params']='Incorrect parameters passed to method';\r
117         $xmlrpcerr['introspect_unknown']=4;\r
118         $xmlrpcstr['introspect_unknown']="Can't introspect: method unknown";\r
119         $xmlrpcerr['http_error']=5;\r
120         $xmlrpcstr['http_error']="Didn't receive 200 OK from remote server.";\r
121         $xmlrpcerr['no_data']=6;\r
122         $xmlrpcstr['no_data']='No data received from server.';\r
123         $xmlrpcerr['no_ssl']=7;\r
124         $xmlrpcstr['no_ssl']='No SSL support compiled in.';\r
125         $xmlrpcerr['curl_fail']=8;\r
126         $xmlrpcstr['curl_fail']='CURL error';\r
127 \r
128 \r
129         $xmlrpcerr['multicall_notstruct'] = 9;\r
130         $xmlrpcstr['multicall_notstruct'] = 'system.multicall expected struct';\r
131         $xmlrpcerr['multicall_nomethod']  = 10;\r
132         $xmlrpcstr['multicall_nomethod']  = 'missing methodName';\r
133         $xmlrpcerr['multicall_notstring'] = 11;\r
134         $xmlrpcstr['multicall_notstring'] = 'methodName is not a string';\r
135         $xmlrpcerr['multicall_recursion'] = 12;\r
136         $xmlrpcstr['multicall_recursion'] = 'recursive system.multicall forbidden';\r
137         $xmlrpcerr['multicall_noparams']  = 13;\r
138         $xmlrpcstr['multicall_noparams']  = 'missing params';\r
139         $xmlrpcerr['multicall_notarray']  = 14;\r
140         $xmlrpcstr['multicall_notarray']  = 'params is not an array';\r
141 \r
142         // The charset encoding expected by the server for received messages and\r
143         // by the client for received responses\r
144         $xmlrpc_defencoding='UTF-8';\r
145         // The encoding used by PHP.\r
146         // String values received will be converted to this.\r
147         $xmlrpc_internalencoding='ISO-8859-1';\r
148 \r
149         $xmlrpcName='XML-RPC for PHP';\r
150         $xmlrpcVersion='1.1.1';\r
151 \r
152         // let user errors start at 800\r
153         $xmlrpcerruser=800;\r
154         // let XML parse errors start at 100\r
155         $xmlrpcerrxml=100;\r
156 \r
157         // formulate backslashes for escaping regexp\r
158         $xmlrpc_backslash=chr(92).chr(92);\r
159 \r
160         // used to store state during parsing\r
161         // quick explanation of components:\r
162         //   st - used to build up a string for evaluation\r
163         //   ac - used to accumulate values\r
164         //   qt - used to decide if quotes are needed for evaluation\r
165         //   cm - used to denote struct or array (comma needed)\r
166         //   isf - used to indicate a fault\r
167         //   lv - used to indicate "looking for a value": implements\r
168         //        the logic to allow values with no types to be strings\r
169         //   params - used to store parameters in method calls\r
170         //   method - used to store method name\r
171 \r
172         $_xh=array();\r
173 \r
174         /**\r
175         * To help correct communication of non-ascii chars inside strings, regardless\r
176         * of the charset used when sending requests, parsing them, sending responses\r
177         * and parsing responses, convert all non-ascii chars present in the message\r
178         * into their equivalent 'charset entity'. Charset entities enumerated this way\r
179         * are independent of the charset encoding used to transmit them, and all XML\r
180         * parsers are bound to understand them.\r
181         */\r
182         function xmlrpc_entity_decode($string)\r
183         {\r
184                 $top=split('&', $string);\r
185                 $op='';\r
186                 $i=0;\r
187                 while($i<sizeof($top))\r
188                 {\r
189                         if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs))\r
190                         {\r
191                                 $op.=ereg_replace("^[#a-zA-Z0-9]+;",\r
192                                 xmlrpc_lookup_entity($regs[1]),\r
193                                 $top[$i]);\r
194                         }\r
195                         else\r
196                         {\r
197                                 if ($i==0)\r
198                                 {\r
199                                         $op=$top[$i];\r
200                                 }\r
201                                 else\r
202                                 {\r
203                                         $op.='&' . $top[$i];\r
204                                 }\r
205                         }\r
206                         $i++;\r
207                 }\r
208                 return $op;\r
209         }\r
210 \r
211         function xmlrpc_lookup_entity($ent)\r
212         {\r
213                 global $xmlEntities;\r
214 \r
215                 if (isset($xmlEntities[strtolower($ent)]))\r
216                 {\r
217                         return $xmlEntities[strtolower($ent)];\r
218                 }\r
219                 if (ereg("^#([0-9]+)$", $ent, $regs))\r
220                 {\r
221                         return chr($regs[1]);\r
222                 }\r
223                 return '?';\r
224         }\r
225 \r
226         /**\r
227          * These entities originate from HTML specs (1.1, proposed 2.0, etc),\r
228          * and are taken directly from php-4.3.1/ext/mbstring/html_entities.c.\r
229          * Until php provides functionality to translate these entities in its\r
230          * core library, use this function.\r
231          */\r
232         function xmlrpc_html_entity_xlate($data = '')\r
233         {\r
234                 $entities = array(\r
235                         "&nbsp;" => "&#160;",\r
236                         "&iexcl;" => "&#161;",\r
237                         "&cent;" => "&#162;",\r
238                         "&pound;" => "&#163;",\r
239                         "&curren;" => "&#164;",\r
240                         "&yen;" => "&#165;",\r
241                         "&brvbar;" => "&#166;",\r
242                         "&sect;" => "&#167;",\r
243                         "&uml;" => "&#168;",\r
244                         "&copy;" => "&#169;",\r
245                         "&ordf;" => "&#170;",\r
246                         "&laquo;" => "&#171;",\r
247                         "&not;" => "&#172;",\r
248                         "&shy;" => "&#173;",\r
249                         "&reg;" => "&#174;",\r
250                         "&macr;" => "&#175;",\r
251                         "&deg;" => "&#176;",\r
252                         "&plusmn;" => "&#177;",\r
253                         "&sup2;" => "&#178;",\r
254                         "&sup3;" => "&#179;",\r
255                         "&acute;" => "&#180;",\r
256                         "&micro;" => "&#181;",\r
257                         "&para;" => "&#182;",\r
258                         "&middot;" => "&#183;",\r
259                         "&cedil;" => "&#184;",\r
260                         "&sup1;" => "&#185;",\r
261                         "&ordm;" => "&#186;",\r
262                         "&raquo;" => "&#187;",\r
263                         "&frac14;" => "&#188;",\r
264                         "&frac12;" => "&#189;",\r
265                         "&frac34;" => "&#190;",\r
266                         "&iquest;" => "&#191;",\r
267                         "&Agrave;" => "&#192;",\r
268                         "&Aacute;" => "&#193;",\r
269                         "&Acirc;" => "&#194;",\r
270                         "&Atilde;" => "&#195;",\r
271                         "&Auml;" => "&#196;",\r
272                         "&Aring;" => "&#197;",\r
273                         "&AElig;" => "&#198;",\r
274                         "&Ccedil;" => "&#199;",\r
275                         "&Egrave;" => "&#200;",\r
276                         "&Eacute;" => "&#201;",\r
277                         "&Ecirc;" => "&#202;",\r
278                         "&Euml;" => "&#203;",\r
279                         "&Igrave;" => "&#204;",\r
280                         "&Iacute;" => "&#205;",\r
281                         "&Icirc;" => "&#206;",\r
282                         "&Iuml;" => "&#207;",\r
283                         "&ETH;" => "&#208;",\r
284                         "&Ntilde;" => "&#209;",\r
285                         "&Ograve;" => "&#210;",\r
286                         "&Oacute;" => "&#211;",\r
287                         "&Ocirc;" => "&#212;",\r
288                         "&Otilde;" => "&#213;",\r
289                         "&Ouml;" => "&#214;",\r
290                         "&times;" => "&#215;",\r
291                         "&Oslash;" => "&#216;",\r
292                         "&Ugrave;" => "&#217;",\r
293                         "&Uacute;" => "&#218;",\r
294                         "&Ucirc;" => "&#219;",\r
295                         "&Uuml;" => "&#220;",\r
296                         "&Yacute;" => "&#221;",\r
297                         "&THORN;" => "&#222;",\r
298                         "&szlig;" => "&#223;",\r
299                         "&agrave;" => "&#224;",\r
300                         "&aacute;" => "&#225;",\r
301                         "&acirc;" => "&#226;",\r
302                         "&atilde;" => "&#227;",\r
303                         "&auml;" => "&#228;",\r
304                         "&aring;" => "&#229;",\r
305                         "&aelig;" => "&#230;",\r
306                         "&ccedil;" => "&#231;",\r
307                         "&egrave;" => "&#232;",\r
308                         "&eacute;" => "&#233;",\r
309                         "&ecirc;" => "&#234;",\r
310                         "&euml;" => "&#235;",\r
311                         "&igrave;" => "&#236;",\r
312                         "&iacute;" => "&#237;",\r
313                         "&icirc;" => "&#238;",\r
314                         "&iuml;" => "&#239;",\r
315                         "&eth;" => "&#240;",\r
316                         "&ntilde;" => "&#241;",\r
317                         "&ograve;" => "&#242;",\r
318                         "&oacute;" => "&#243;",\r
319                         "&ocirc;" => "&#244;",\r
320                         "&otilde;" => "&#245;",\r
321                         "&ouml;" => "&#246;",\r
322                         "&divide;" => "&#247;",\r
323                         "&oslash;" => "&#248;",\r
324                         "&ugrave;" => "&#249;",\r
325                         "&uacute;" => "&#250;",\r
326                         "&ucirc;" => "&#251;",\r
327                         "&uuml;" => "&#252;",\r
328                         "&yacute;" => "&#253;",\r
329                         "&thorn;" => "&#254;",\r
330                         "&yuml;" => "&#255;",\r
331                         "&OElig;" => "&#338;",\r
332                         "&oelig;" => "&#339;",\r
333                         "&Scaron;" => "&#352;",\r
334                         "&scaron;" => "&#353;",\r
335                         "&Yuml;" => "&#376;",\r
336                         "&fnof;" => "&#402;",\r
337                         "&circ;" => "&#710;",\r
338                         "&tilde;" => "&#732;",\r
339                         "&Alpha;" => "&#913;",\r
340                         "&Beta;" => "&#914;",\r
341                         "&Gamma;" => "&#915;",\r
342                         "&Delta;" => "&#916;",\r
343                         "&Epsilon;" => "&#917;",\r
344                         "&Zeta;" => "&#918;",\r
345                         "&Eta;" => "&#919;",\r
346                         "&Theta;" => "&#920;",\r
347                         "&Iota;" => "&#921;",\r
348                         "&Kappa;" => "&#922;",\r
349                         "&Lambda;" => "&#923;",\r
350                         "&Mu;" => "&#924;",\r
351                         "&Nu;" => "&#925;",\r
352                         "&Xi;" => "&#926;",\r
353                         "&Omicron;" => "&#927;",\r
354                         "&Pi;" => "&#928;",\r
355                         "&Rho;" => "&#929;",\r
356                         "&Sigma;" => "&#931;",\r
357                         "&Tau;" => "&#932;",\r
358                         "&Upsilon;" => "&#933;",\r
359                         "&Phi;" => "&#934;",\r
360                         "&Chi;" => "&#935;",\r
361                         "&Psi;" => "&#936;",\r
362                         "&Omega;" => "&#937;",\r
363                         "&beta;" => "&#946;",\r
364                         "&gamma;" => "&#947;",\r
365                         "&delta;" => "&#948;",\r
366                         "&epsilon;" => "&#949;",\r
367                         "&zeta;" => "&#950;",\r
368                         "&eta;" => "&#951;",\r
369                         "&theta;" => "&#952;",\r
370                         "&iota;" => "&#953;",\r
371                         "&kappa;" => "&#954;",\r
372                         "&lambda;" => "&#955;",\r
373                         "&mu;" => "&#956;",\r
374                         "&nu;" => "&#957;",\r
375                         "&xi;" => "&#958;",\r
376                         "&omicron;" => "&#959;",\r
377                         "&pi;" => "&#960;",\r
378                         "&rho;" => "&#961;",\r
379                         "&sigmaf;" => "&#962;",\r
380                         "&sigma;" => "&#963;",\r
381                         "&tau;" => "&#964;",\r
382                         "&upsilon;" => "&#965;",\r
383                         "&phi;" => "&#966;",\r
384                         "&chi;" => "&#967;",\r
385                         "&psi;" => "&#968;",\r
386                         "&omega;" => "&#969;",\r
387                         "&thetasym;" => "&#977;",\r
388                         "&upsih;" => "&#978;",\r
389                         "&piv;" => "&#982;",\r
390                         "&ensp;" => "&#8194;",\r
391                         "&emsp;" => "&#8195;",\r
392                         "&thinsp;" => "&#8201;",\r
393                         "&zwnj;" => "&#8204;",\r
394                         "&zwj;" => "&#8205;",\r
395                         "&lrm;" => "&#8206;",\r
396                         "&rlm;" => "&#8207;",\r
397                         "&ndash;" => "&#8211;",\r
398                         "&mdash;" => "&#8212;",\r
399                         "&lsquo;" => "&#8216;",\r
400                         "&rsquo;" => "&#8217;",\r
401                         "&sbquo;" => "&#8218;",\r
402                         "&ldquo;" => "&#8220;",\r
403                         "&rdquo;" => "&#8221;",\r
404                         "&bdquo;" => "&#8222;",\r
405                         "&dagger;" => "&#8224;",\r
406                         "&Dagger;" => "&#8225;",\r
407                         "&bull;" => "&#8226;",\r
408                         "&hellip;" => "&#8230;",\r
409                         "&permil;" => "&#8240;",\r
410                         "&prime;" => "&#8242;",\r
411                         "&Prime;" => "&#8243;",\r
412                         "&lsaquo;" => "&#8249;",\r
413                         "&rsaquo;" => "&#8250;",\r
414                         "&oline;" => "&#8254;",\r
415                         "&frasl;" => "&#8260;",\r
416                         "&euro;" => "&#8364;",\r
417                         "&weierp;" => "&#8472;",\r
418                         "&image;" => "&#8465;",\r
419                         "&real;" => "&#8476;",\r
420                         "&trade;" => "&#8482;",\r
421                         "&alefsym;" => "&#8501;",\r
422                         "&larr;" => "&#8592;",\r
423                         "&uarr;" => "&#8593;",\r
424                         "&rarr;" => "&#8594;",\r
425                         "&darr;" => "&#8595;",\r
426                         "&harr;" => "&#8596;",\r
427                         "&crarr;" => "&#8629;",\r
428                         "&lArr;" => "&#8656;",\r
429                         "&uArr;" => "&#8657;",\r
430                         "&rArr;" => "&#8658;",\r
431                         "&dArr;" => "&#8659;",\r
432                         "&hArr;" => "&#8660;",\r
433                         "&forall;" => "&#8704;",\r
434                         "&part;" => "&#8706;",\r
435                         "&exist;" => "&#8707;",\r
436                         "&empty;" => "&#8709;",\r
437                         "&nabla;" => "&#8711;",\r
438                         "&isin;" => "&#8712;",\r
439                         "&notin;" => "&#8713;",\r
440                         "&ni;" => "&#8715;",\r
441                         "&prod;" => "&#8719;",\r
442                         "&sum;" => "&#8721;",\r
443                         "&minus;" => "&#8722;",\r
444                         "&lowast;" => "&#8727;",\r
445                         "&radic;" => "&#8730;",\r
446                         "&prop;" => "&#8733;",\r
447                         "&infin;" => "&#8734;",\r
448                         "&ang;" => "&#8736;",\r
449                         "&and;" => "&#8743;",\r
450                         "&or;" => "&#8744;",\r
451                         "&cap;" => "&#8745;",\r
452                         "&cup;" => "&#8746;",\r
453                         "&int;" => "&#8747;",\r
454                         "&there4;" => "&#8756;",\r
455                         "&sim;" => "&#8764;",\r
456                         "&cong;" => "&#8773;",\r
457                         "&asymp;" => "&#8776;",\r
458                         "&ne;" => "&#8800;",\r
459                         "&equiv;" => "&#8801;",\r
460                         "&le;" => "&#8804;",\r
461                         "&ge;" => "&#8805;",\r
462                         "&sub;" => "&#8834;",\r
463                         "&sup;" => "&#8835;",\r
464                         "&nsub;" => "&#8836;",\r
465                         "&sube;" => "&#8838;",\r
466                         "&supe;" => "&#8839;",\r
467                         "&oplus;" => "&#8853;",\r
468                         "&otimes;" => "&#8855;",\r
469                         "&perp;" => "&#8869;",\r
470                         "&sdot;" => "&#8901;",\r
471                         "&lceil;" => "&#8968;",\r
472                         "&rceil;" => "&#8969;",\r
473                         "&lfloor;" => "&#8970;",\r
474                         "&rfloor;" => "&#8971;",\r
475                         "&lang;" => "&#9001;",\r
476                         "&rang;" => "&#9002;",\r
477                         "&loz;" => "&#9674;",\r
478                         "&spades;" => "&#9824;",\r
479                         "&clubs;" => "&#9827;",\r
480                         "&hearts;" => "&#9829;",\r
481                         "&diams;" => "&#9830;");\r
482                 return strtr($data, $entities);\r
483         }\r
484 \r
485         function xmlrpc_encode_entitites($data) \r
486         {\r
487                 $length = strlen($data);\r
488                 $escapeddata = "";\r
489                 for($position = 0; $position < $length; $position++)\r
490                 {\r
491                         $character = substr($data, $position, 1);\r
492                         $code = Ord($character);\r
493                         switch($code) {\r
494                                 case 34:\r
495                                 $character = "&quot;";\r
496                                 break;\r
497                                 case 38:\r
498                                 $character = "&amp;";\r
499                                 break;\r
500                                 case 39:\r
501                                 $character = "&apos;";\r
502                                 break;\r
503                                 case 60:\r
504                                 $character = "&lt;";\r
505                                 break;\r
506                                 case 62:\r
507                                 $character = "&gt;";\r
508                                 break;\r
509                                 default:\r
510                                 if ($code < 32 || $code > 159)\r
511                                         $character = ("&#".strval($code).";");\r
512                                 break;\r
513                         }\r
514                         $escapeddata .= $character;\r
515                 }\r
516                 return $escapeddata;\r
517         }\r
518 \r
519         function xmlrpc_se($parser, $name, $attrs)\r
520         {\r
521                 global $_xh, $xmlrpcDateTime, $xmlrpcString;\r
522 \r
523                 switch($name)\r
524                 {\r
525                         case 'STRUCT':\r
526                         case 'ARRAY':\r
527                                 $_xh[$parser]['st'].='array(';\r
528                                 $_xh[$parser]['cm']++;\r
529                                 // this last line turns quoting off\r
530                                 // this means if we get an empty array we'll\r
531                                 // simply get a bit of whitespace in the eval\r
532                                 $_xh[$parser]['qt']=0;\r
533                                 break;\r
534                         case 'NAME':\r
535                                 $_xh[$parser]['st'].='"';\r
536                                 $_xh[$parser]['ac']='';\r
537                                 break;\r
538                         case 'FAULT':\r
539                                 $_xh[$parser]['isf']=1;\r
540                                 break;\r
541                         case 'PARAM':\r
542                                 $_xh[$parser]['st']='';\r
543                                 break;\r
544                         case 'VALUE':\r
545                                 $_xh[$parser]['st'].='new xmlrpcval(';\r
546                                 $_xh[$parser]['vt']=$xmlrpcString;\r
547                                 $_xh[$parser]['ac']='';\r
548                                 $_xh[$parser]['qt']=0;\r
549                                 $_xh[$parser]['lv']=1;\r
550                                 // look for a value: if this is still 1 by the\r
551                                 // time we reach the first data segment then the type is string\r
552                                 // by implication and we need to add in a quote\r
553                                 break;\r
554                         case 'I4':\r
555                         case 'INT':\r
556                         case 'STRING':\r
557                         case 'BOOLEAN':\r
558                         case 'DOUBLE':\r
559                         case 'DATETIME.ISO8601':\r
560                         case 'BASE64':\r
561                                 $_xh[$parser]['ac']=''; // reset the accumulator\r
562 \r
563                                 if ($name=='DATETIME.ISO8601' || $name=='STRING')\r
564                                 {\r
565                                         $_xh[$parser]['qt']=1;\r
566                                         if ($name=='DATETIME.ISO8601')\r
567                                         {\r
568                                                 $_xh[$parser]['vt']=$xmlrpcDateTime;\r
569                                         }\r
570                                 }\r
571                                 elseif ($name=='BASE64')\r
572                                 {\r
573                                         $_xh[$parser]['qt']=2;\r
574                                 }\r
575                                 else\r
576                                 {\r
577                                         // No quoting is required here -- but\r
578                                         // at the end of the element we must check\r
579                                         // for data format errors.\r
580                                         $_xh[$parser]['qt']=0;\r
581                                 }\r
582                                 break;\r
583                         case 'MEMBER':\r
584                                 $_xh[$parser]['ac']='';\r
585                                 break;\r
586                         default:\r
587                                 break;\r
588                 }\r
589 \r
590                 if ($name!='VALUE')\r
591                 {\r
592                         $_xh[$parser]['lv']=0;\r
593                 }\r
594         }\r
595 \r
596         function xmlrpc_ee($parser, $name)\r
597         {\r
598                 global $_xh,$xmlrpcTypes,$xmlrpcString;\r
599 \r
600                 switch($name)\r
601                 {\r
602                         case 'STRUCT':\r
603                         case 'ARRAY':\r
604                                 if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',')\r
605                                 {\r
606                                         $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1);\r
607                                 }\r
608                                 $_xh[$parser]['st'].=')';\r
609                                 $_xh[$parser]['vt']=strtolower($name);\r
610                                 $_xh[$parser]['cm']--;\r
611                                 break;\r
612                         case 'NAME':\r
613                                 $_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => ';\r
614                                 break;\r
615                         case 'BOOLEAN':\r
616                                 // special case here: we translate boolean 1 or 0 into PHP\r
617                                 // constants true or false\r
618                                 // NB: this simple checks helps a lot sanitizing input, ie no\r
619                                 // security problems around here\r
620                                 if ($_xh[$parser]['ac']=='1')\r
621                                 {\r
622                                         $_xh[$parser]['ac']='true';\r
623                                 }\r
624                                 else\r
625                                 {\r
626                                         $_xh[$parser]['ac']='false';\r
627                                 }\r
628                                 $_xh[$parser]['vt']=strtolower($name);\r
629                                 // Drop through intentionally.\r
630                         case 'I4':\r
631                         case 'INT':\r
632                         case 'STRING':\r
633                         case 'DOUBLE':\r
634                         case 'DATETIME.ISO8601':\r
635                         case 'BASE64':\r
636                                 if ($_xh[$parser]['qt']==1)\r
637                                 {\r
638                                         // we use double quotes rather than single so backslashification works OK\r
639                                         $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"';\r
640                                 }\r
641                                 elseif ($_xh[$parser]['qt']==2)\r
642                                 {\r
643                                         $_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")';\r
644                                 }\r
645                                 elseif ($name=='BOOLEAN')\r
646                                 {\r
647                                         $_xh[$parser]['st'].=$_xh[$parser]['ac'];\r
648                                 }\r
649                                 elseif ($name=='DOUBLE')\r
650                                 {\r
651                                         // we have a DOUBLE\r
652                                         // we must check that only 0123456789-.<space> are characters here\r
653                                         if (!ereg("^[+-]?[eE0123456789 \\t\\.]+$", $_xh[$parser]['ac']))\r
654                                         {\r
655                                                 // TODO: find a better way of throwing an error\r
656                                                 // than this!\r
657                                                 error_log('XML-RPC: non numeric value received in DOUBLE: '.$_xh[$parser]['ac']);\r
658                                                 $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'";\r
659                                         }\r
660                                         else\r
661                                         {\r
662                                                 // it's ok, add it on\r
663                                                 $_xh[$parser]['st'].=(double)$_xh[$parser]['ac'];\r
664                                         }\r
665                                 }\r
666                                 else\r
667                                 {\r
668                                         // we have an I4/INT\r
669                                         // we must check that only 0123456789-<space> are characters here\r
670                                         if (!ereg("^[+-]?[0123456789 \\t]+$", $_xh[$parser]['ac']))\r
671                                         {\r
672                                                 // TODO: find a better way of throwing an error\r
673                                                 // than this!\r
674                                                 error_log('XML-RPC: non numeric value received in INT: '.$_xh[$parser]['ac']);\r
675                                                 $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'";\r
676                                         }\r
677                                         else\r
678                                         {\r
679                                                 // it's ok, add it on\r
680                                                 $_xh[$parser]['st'].=(int)$_xh[$parser]['ac'];\r
681                                         }\r
682                                 }\r
683                                 $_xh[$parser]['ac']='';\r
684                                 $_xh[$parser]['qt']=0;\r
685                                 $_xh[$parser]['lv']=3; // indicate we've found a value\r
686                                 break;\r
687                         case 'VALUE':\r
688                                 // deal with a string value\r
689                                 if (strlen($_xh[$parser]['ac'])>0 &&\r
690                                         $_xh[$parser]['vt']==$xmlrpcString)\r
691                                 {\r
692                                         $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"';\r
693                                 }\r
694                                 // This if() detects if no scalar was inside <VALUE></VALUE>\r
695                                 // and pads an empty ''.\r
696                                 if($_xh[$parser]['st'][strlen($_xh[$parser]['st'])-1] == '(')\r
697                                 {\r
698                                         $_xh[$parser]['st'].= '""';\r
699                                 }\r
700                                 // G. Giunta 2005/03/12 save some chars in the reconstruction of string vals...\r
701                                 if ($_xh[$parser]['vt'] != $xmlrpcString)\r
702                                         $_xh[$parser]['st'].=", '" . $_xh[$parser]['vt'] . "')";\r
703                                 else\r
704                                         $_xh[$parser]['st'].=")";\r
705                                 if ($_xh[$parser]['cm'])\r
706                                 {\r
707                                         $_xh[$parser]['st'].=',';\r
708                                 }\r
709                                 break;\r
710                         case 'MEMBER':\r
711                                 $_xh[$parser]['ac']='';\r
712                                 $_xh[$parser]['qt']=0;\r
713                                 break;\r
714                         case 'DATA':\r
715                                 $_xh[$parser]['ac']='';\r
716                                 $_xh[$parser]['qt']=0;\r
717                                 break;\r
718                         case 'PARAM':\r
719                                 $_xh[$parser]['params'][]=$_xh[$parser]['st'];\r
720                                 break;\r
721                         case 'METHODNAME':\r
722                                 $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", '', $_xh[$parser]['ac']);\r
723                                 break;\r
724                         // BOOLEAN HAS BEEN ENUMERATED ABOVE!\r
725                         /*case 'BOOLEAN':\r
726                                 // special case here: we translate boolean 1 or 0 into PHP\r
727                                 // constants true or false\r
728                                 if ($_xh[$parser]['ac']=='1')\r
729                                 {\r
730                                         $_xh[$parser]['ac']='true';\r
731                                 }\r
732                                 else\r
733                                 {\r
734                                         $_xh[$parser]['ac']='false';\r
735                                         $_xh[$parser]['vt']=strtolower($name);\r
736                                 }\r
737                                 break;*/\r
738                         default:\r
739                                 break;\r
740                 }\r
741                 // if it's a valid type name, set the type\r
742                 if (isset($xmlrpcTypes[strtolower($name)]))\r
743                 {\r
744                         $_xh[$parser]['vt']=strtolower($name);\r
745                 }\r
746         }\r
747 \r
748         function xmlrpc_cd($parser, $data)\r
749         {\r
750                 global $_xh, $xmlrpc_backslash;\r
751 \r
752                 //if (ereg("^[\n\r \t]+$", $data)) return;\r
753                 // print "adding [${data}]\n";\r
754 \r
755                 if ($_xh[$parser]['lv']!=3)\r
756                 {\r
757                         // "lookforvalue==3" means that we've found an entire value\r
758                         // and should discard any further character data\r
759                         if ($_xh[$parser]['lv']==1)\r
760                         {\r
761                                 // if we've found text and we're just in a <value> then\r
762                                 // turn quoting on, as this will be a string\r
763                                 $_xh[$parser]['qt']=1;\r
764                                 // and say we've found a value\r
765                                 $_xh[$parser]['lv']=2;\r
766                         }\r
767                         if(!@isset($_xh[$parser]['ac']))\r
768                         {\r
769                                 $_xh[$parser]['ac'] = '';\r
770                         }\r
771                         $_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data)));\r
772                 }\r
773         }\r
774 \r
775         function xmlrpc_dh($parser, $data)\r
776         {\r
777                 global $_xh, $xmlrpc_backslash;\r
778                 if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';')\r
779                 {\r
780                         if ($_xh[$parser]['lv']==1)\r
781                         {\r
782                                 $_xh[$parser]['qt']=1;\r
783                                 $_xh[$parser]['lv']=2;\r
784                         }\r
785                         $_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data)));\r
786                 }\r
787         }\r
788 \r
789         class xmlrpc_client\r
790         {\r
791                 var $path;\r
792                 var $server;\r
793                 var $port;\r
794                 var $errno;\r
795                 var $errstr;\r
796                 var $debug=0;\r
797                 var $username='';\r
798                 var $password='';\r
799                 var $cert='';\r
800                 var $certpass='';\r
801                 var $verifypeer=1;\r
802                 var $verifyhost=1;\r
803                 var $no_multicall=false;\r
804 \r
805                 function xmlrpc_client($path, $server, $port=0)\r
806                 {\r
807                         $this->port=$port; $this->server=$server; $this->path=$path;\r
808                 }\r
809 \r
810                 function setDebug($in)\r
811                 {\r
812                         if ($in)\r
813                         {\r
814                                 $this->debug=1;\r
815                         }\r
816                         else\r
817                         {\r
818                                 $this->debug=0;\r
819                         }\r
820                 }\r
821 \r
822                 function setCredentials($u, $p)\r
823                 {\r
824                         $this->username=$u;\r
825                         $this->password=$p;\r
826                 }\r
827 \r
828                 function setCertificate($cert, $certpass)\r
829                 {\r
830                         $this->cert = $cert;\r
831                         $this->certpass = $certpass;\r
832                 }\r
833 \r
834                 function setSSLVerifyPeer($i)\r
835                 {\r
836                         $this->verifypeer = $i;\r
837                 }\r
838 \r
839                 function setSSLVerifyHost($i)\r
840                 {\r
841                         $this->verifyhost = $i;\r
842                 }\r
843 \r
844                 function send($msg, $timeout=0, $method='http')\r
845                 {\r
846                         if (is_array($msg))\r
847                         {\r
848                                 // $msg is an array of xmlrpcmsg's\r
849                                 return $this->multicall($msg, $timeout, $method);\r
850                         }\r
851 \r
852                         // where msg is an xmlrpcmsg\r
853                         $msg->debug=$this->debug;\r
854 \r
855                         if ($method == 'https')\r
856                         {\r
857                                 return $this->sendPayloadHTTPS($msg,\r
858                                 $this->server,\r
859                                 $this->port, $timeout,\r
860                                 $this->username, $this->password,\r
861                                 $this->cert,\r
862                                 $this->certpass);\r
863                         }\r
864                         else\r
865                         {\r
866                                 return $this->sendPayloadHTTP10($msg, $this->server, $this->port,\r
867                                 $timeout, $this->username, \r
868                                 $this->password);\r
869                         }\r
870                 }\r
871 \r
872                 function sendPayloadHTTP10($msg, $server, $port, $timeout=0,$username='', $password='')\r
873                 {\r
874                         global $xmlrpcerr, $xmlrpcstr, $xmlrpcName, $xmlrpcVersion, $xmlrpc_defencoding;\r
875                         if ($port==0)\r
876                         {\r
877                                 $port=80;\r
878                         }\r
879                         if($timeout>0)\r
880                         {\r
881                                 $fp=@fsockopen($server, $port,$this->errno, $this->errstr, $timeout);\r
882                         }\r
883                         else\r
884                         {\r
885                                 $fp=@fsockopen($server, $port,$this->errno, $this->errstr);\r
886                         }\r
887                         if ($fp)\r
888                         {\r
889                                 if ($timeout>0 && function_exists('stream_set_timeout'))\r
890                                         stream_set_timeout($fp, $timeout);\r
891                         }\r
892                         else\r
893                         {\r
894                                 $this->errstr='Connect error';\r
895                                 $r=new xmlrpcresp(0, $xmlrpcerr['http_error'],$xmlrpcstr['http_error']);\r
896                                 return $r;\r
897                         }\r
898                         // Only create the payload if it was not created previously\r
899                         if(empty($msg->payload))\r
900                         {\r
901                                 $msg->createPayload();\r
902                         }\r
903 \r
904                         // thanks to Grant Rauscher <grant7@firstworld.net>\r
905                         // for this\r
906                         $credentials='';\r
907                         if ($username!='')\r
908                         {\r
909                                 $credentials='Authorization: Basic ' . base64_encode($username . ':' . $password) . "\r\n";\r
910                         }\r
911 \r
912                         $op= "POST " . $this->path. " HTTP/1.0\r\n" .\r
913                                 "User-Agent: " . $xmlrpcName . " " . $xmlrpcVersion . "\r\n" .\r
914                                 "Host: ". $server . "\r\n" .\r
915                                 $credentials . \r
916                                 "Accept-Charset: " . $xmlrpc_defencoding . "\r\n" .\r
917                                 "Content-Type: text/xml\r\nContent-Length: " .\r
918                                 strlen($msg->payload) . "\r\n\r\n" .\r
919                                 $msg->payload;\r
920 \r
921                         if (!fputs($fp, $op, strlen($op)))\r
922                         {\r
923                                 $this->errstr='Write error';\r
924                                 $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']);\r
925                                 return $r;\r
926                         }\r
927                         $resp=$msg->parseResponseFile($fp);\r
928                         fclose($fp);\r
929                         return $resp;\r
930                 }\r
931 \r
932                 // contributed by Justin Miller <justin@voxel.net>\r
933                 // requires curl to be built into PHP\r
934                 function sendPayloadHTTPS($msg, $server, $port, $timeout=0,$username='', $password='', $cert='',$certpass='')\r
935                 {\r
936                         global $xmlrpcerr, $xmlrpcstr, $xmlrpcVersion, $xmlrpc_internalencoding;\r
937                         if ($port == 0)\r
938                         {\r
939                                 $port = 443;\r
940                         }\r
941 \r
942                         // Only create the payload if it was not created previously\r
943                         if(empty($msg->payload))\r
944                         {\r
945                                 $msg->createPayload();\r
946                         }\r
947 \r
948                         if (!function_exists('curl_init'))\r
949                         {\r
950                                 $this->errstr='SSL unavailable on this install';\r
951                                 $r=new xmlrpcresp(0, $xmlrpcerr['no_ssl'], $xmlrpcstr['no_ssl']);\r
952                                 return $r;\r
953                         }\r
954 \r
955                         $curl = curl_init('https://' . $server . ':' . $port . $this->path);\r
956 \r
957                         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);\r
958                         // results into variable\r
959                         if ($this->debug)\r
960                         {\r
961                                 curl_setopt($curl, CURLOPT_VERBOSE, 1);\r
962                         }\r
963                         curl_setopt($curl, CURLOPT_USERAGENT, 'PHP XMLRPC '.$xmlrpcVersion);\r
964                         // required for XMLRPC\r
965                         curl_setopt($curl, CURLOPT_POST, 1);\r
966                         // post the data\r
967                         curl_setopt($curl, CURLOPT_POSTFIELDS, $msg->payload);\r
968                         // the data\r
969                         curl_setopt($curl, CURLOPT_HEADER, 1);\r
970                         // return the header too\r
971                         curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: text/xml', 'Accept-Charset: '.$xmlrpc_internalencoding));\r
972                         // whether to verify remote host's cert\r
973                         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verifypeer);\r
974                         // whether to verify cert's common name (CN); 0 for no, 1 to verify that it exists, and 2 to verify that it matches the hostname used\r
975                         curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, $this->verifyhost);\r
976                         // required for XMLRPC\r
977                         if ($timeout)\r
978                         {\r
979                                 curl_setopt($curl, CURLOPT_TIMEOUT, $timeout == 1 ? 1 : $timeout - 1);\r
980                         }\r
981                         // timeout is borked\r
982                         if ($username && $password)\r
983                         {\r
984                                 curl_setopt($curl, CURLOPT_USERPWD,"$username:$password");\r
985                         }\r
986                         // set auth stuff\r
987                         if ($cert)\r
988                         {\r
989                                 curl_setopt($curl, CURLOPT_SSLCERT, $cert);\r
990                         }\r
991                         // set cert file\r
992                         if ($certpass)\r
993                         {\r
994                                 curl_setopt($curl, CURLOPT_SSLCERTPASSWD,$certpass);\r
995                         }\r
996                         // set cert password\r
997 \r
998                         $result = curl_exec($curl);\r
999 \r
1000                         if (!$result)\r
1001                         {\r
1002                                 $this->errstr='no response';\r
1003                                 $resp=new xmlrpcresp(0, $xmlrpcerr['curl_fail'], $xmlrpcstr['curl_fail']. ': '. curl_error($curl));\r
1004                                 curl_close($curl);\r
1005                         }\r
1006                         else\r
1007                         {\r
1008                                 curl_close($curl);\r
1009                                 $resp = $msg->parseResponse($result);\r
1010                         }\r
1011                         return $resp;\r
1012                 }\r
1013 \r
1014                 function multicall($msgs, $timeout=0, $method='http')\r
1015                 {\r
1016                         $results = false;\r
1017 \r
1018                         if (! $this->no_multicall)\r
1019                         {\r
1020                                 $results = $this->_try_multicall($msgs, $timeout, $method);\r
1021                                 /* TODO - this is not php3-friendly */\r
1022                                 // if($results !== false)\r
1023                                 if(is_array($results))\r
1024                                 {\r
1025                                         // Either the system.multicall succeeded, or the send\r
1026                                         // failed (e.g. due to HTTP timeout). In either case,\r
1027                                         // we're done for now.\r
1028                                         return $results;\r
1029                                 }\r
1030                                 else\r
1031                                 {\r
1032                                         // system.multicall unsupported by server,\r
1033                                         // don't try it next time...\r
1034                                         $this->no_multicall = true;\r
1035                                 }\r
1036                         }\r
1037 \r
1038                         // system.multicall is unupported by server:\r
1039                         //   Emulate multicall via multiple requests\r
1040                         $results = array();\r
1041                         //foreach($msgs as $msg)\r
1042                         @reset($msgs);\r
1043                         while(list(,$msg) = @each($msgs))\r
1044                         {\r
1045                                 $results[] = $this->send($msg, $timeout, $method);\r
1046                         }\r
1047                         return $results;\r
1048                 }\r
1049 \r
1050                 // Attempt to boxcar $msgs via system.multicall.\r
1051                 function _try_multicall($msgs, $timeout, $method)\r
1052                 {\r
1053                         // Construct multicall message\r
1054                         $calls = array();\r
1055                         //foreach($msgs as $msg)\r
1056                         @reset($msgs);\r
1057                         while(list(,$msg) = @each($msgs))\r
1058                         {\r
1059                                 $call['methodName'] = new xmlrpcval($msg->method(),'string');\r
1060                                 $numParams = $msg->getNumParams();\r
1061                                 $params = array();\r
1062                                 for ($i = 0; $i < $numParams; $i++)\r
1063                                 {\r
1064                                         $params[$i] = $msg->getParam($i);\r
1065                                 }\r
1066                                 $call['params'] = new xmlrpcval($params, 'array');\r
1067                                 $calls[] = new xmlrpcval($call, 'struct');\r
1068                         }\r
1069                         $multicall = new xmlrpcmsg('system.multicall');\r
1070                         $multicall->addParam(new xmlrpcval($calls, 'array'));\r
1071 \r
1072                         // Attempt RPC call\r
1073                         $result = $this->send($multicall, $timeout, $method);\r
1074                         if(!is_object($result))\r
1075                         {\r
1076                                 return ($result || 0); // transport failed\r
1077                         }\r
1078 \r
1079                         if($result->faultCode() != 0)\r
1080                         {\r
1081                                 return false;           // system.multicall failed\r
1082                         }\r
1083 \r
1084                         // Unpack responses.\r
1085                         $rets = $result->value();\r
1086                         if($rets->kindOf() != 'array')\r
1087                         {\r
1088                                 return false;           // bad return type from system.multicall\r
1089                         }\r
1090                         $numRets = $rets->arraysize();\r
1091                         if($numRets != count($msgs))\r
1092                         {\r
1093                                 return false;           // wrong number of return values.\r
1094                         }\r
1095 \r
1096                         $response = array();\r
1097                         for ($i = 0; $i < $numRets; $i++)\r
1098                         {\r
1099                                 $val = $rets->arraymem($i);\r
1100                                 switch ($val->kindOf())\r
1101                                 {\r
1102                                 case 'array':\r
1103                                         if($val->arraysize() != 1)\r
1104                                         {\r
1105                                                 return false;           // Bad value\r
1106                                         }\r
1107                                         // Normal return value\r
1108                                         $response[$i] = new xmlrpcresp($val->arraymem(0));\r
1109                                         break;\r
1110                                 case 'struct':\r
1111                                         $code = $val->structmem('faultCode');\r
1112                                         if($code->kindOf() != 'scalar' || $code->scalartyp() != 'int')\r
1113                                         {\r
1114                                                 return false;\r
1115                                         }\r
1116                                         $str = $val->structmem('faultString');\r
1117                                         if($str->kindOf() != 'scalar' || $str->scalartyp() != 'string')\r
1118                                         {\r
1119                                                 return false;\r
1120                                         }\r
1121                                         $response[$i] = new xmlrpcresp(0, $code->scalarval(), $str->scalarval());\r
1122                                         break;\r
1123                                 default:\r
1124                                         return false;\r
1125                                 }\r
1126                         }\r
1127                         return $response;\r
1128                 }\r
1129         } // end class xmlrpc_client\r
1130 \r
1131         class xmlrpcresp\r
1132         {\r
1133                 var $val = 0;\r
1134                 var $errno = 0;\r
1135                 var $errstr = '';\r
1136                 var $hdrs = array();\r
1137 \r
1138                 function xmlrpcresp($val, $fcode = 0, $fstr = '')\r
1139                 {\r
1140                         if ($fcode != 0)\r
1141                         {\r
1142                                 // error\r
1143                                 $this->errno = $fcode;\r
1144                                 $this->errstr = $fstr;\r
1145                                 //$this->errstr = htmlspecialchars($fstr); // XXX: encoding probably shouldn't be done here; fix later.\r
1146                         }\r
1147                         elseif (!is_object($val))\r
1148                         {\r
1149                                 // programmer error\r
1150                                 error_log("Invalid type '" . gettype($val) . "' (value: $val) passed to xmlrpcresp. Defaulting to empty value.");\r
1151                                 $this->val = new xmlrpcval();\r
1152                         }\r
1153                         else\r
1154                         {\r
1155                                 // success\r
1156                                 $this->val = $val;\r
1157                         }\r
1158                 }\r
1159 \r
1160                 function faultCode()\r
1161                 {\r
1162                         return $this->errno;\r
1163                 }\r
1164 \r
1165                 function faultString()\r
1166                 {\r
1167                         return $this->errstr;\r
1168                 }\r
1169 \r
1170                 function value()\r
1171                 {\r
1172                         return $this->val;\r
1173                 }\r
1174 \r
1175                 function serialize()\r
1176                 {\r
1177                         $result = "<methodResponse>\n";\r
1178                         if ($this->errno)\r
1179                         {\r
1180                                 // G. Giunta 2005/2/13: let non-ASCII response messages be tolerated by clients\r
1181                                 $result .= '<fault>\r
1182 <value>\r
1183 <struct>\r
1184 <member>\r
1185 <name>faultCode</name>\r
1186 <value><int>' . $this->errno . '</int></value>\r
1187 </member>\r
1188 <member>\r
1189 <name>faultString</name>\r
1190 <value><string>' . xmlrpc_encode_entitites($this->errstr) . '</string></value>\r
1191 </member>\r
1192 </struct>\r
1193 </value>\r
1194 </fault>';\r
1195                         }\r
1196                         else\r
1197                         {\r
1198                                 $result .= "<params>\n<param>\n" .\r
1199                                         $this->val->serialize() . \r
1200                                         "</param>\n</params>";\r
1201                         }\r
1202                         $result .= "\n</methodResponse>";\r
1203                         return $result;\r
1204                 }\r
1205         }\r
1206 \r
1207         class xmlrpcmsg\r
1208         {\r
1209                 var $payload;\r
1210                 var $methodname;\r
1211                 var $params=array();\r
1212                 var $debug=0;\r
1213 \r
1214                 function xmlrpcmsg($meth, $pars=0)\r
1215                 {\r
1216                         $this->methodname=$meth;\r
1217                         if (is_array($pars) && sizeof($pars)>0)\r
1218                         {\r
1219                                 for($i=0; $i<sizeof($pars); $i++)\r
1220                                 {\r
1221                                         $this->addParam($pars[$i]);\r
1222                                 }\r
1223                         }\r
1224                 }\r
1225 \r
1226                 function xml_header()\r
1227                 {\r
1228                         return "<?xml version=\"1.0\"?" . ">\n<methodCall>\n";\r
1229                 }\r
1230 \r
1231                 function xml_footer()\r
1232                 {\r
1233                         return "</methodCall>\n";\r
1234                 }\r
1235 \r
1236                 function createPayload()\r
1237                 {\r
1238                         $this->payload=$this->xml_header();\r
1239                         $this->payload.='<methodName>' . $this->methodname . "</methodName>\n";\r
1240                         //      if (sizeof($this->params)) {\r
1241                         $this->payload.="<params>\n";\r
1242                         for($i=0; $i<sizeof($this->params); $i++)\r
1243                         {\r
1244                                 $p=$this->params[$i];\r
1245                                 $this->payload.="<param>\n" . $p->serialize() .\r
1246                                 "</param>\n";\r
1247                         }\r
1248                         $this->payload.="</params>\n";\r
1249                         // }\r
1250                         $this->payload.=$this->xml_footer();\r
1251                         //$this->payload=str_replace("\n", "\r\n", $this->payload);\r
1252                 }\r
1253 \r
1254                 function method($meth='')\r
1255                 {\r
1256                         if ($meth!='')\r
1257                         {\r
1258                                 $this->methodname=$meth;\r
1259                         }\r
1260                         return $this->methodname;\r
1261                 }\r
1262 \r
1263                 function serialize()\r
1264                 {\r
1265                         $this->createPayload();\r
1266                         return $this->payload;\r
1267                 }\r
1268 \r
1269                 function addParam($par) { $this->params[]=$par; }\r
1270                 function getParam($i) { return $this->params[$i]; }\r
1271                 function getNumParams() { return sizeof($this->params); }\r
1272 \r
1273                 function parseResponseFile($fp)\r
1274                 {\r
1275                         $ipd='';\r
1276                         while($data=fread($fp, 32768))\r
1277                         {\r
1278                                 $ipd.=$data;\r
1279                         }\r
1280                         return $this->parseResponse($ipd);\r
1281                 }\r
1282 \r
1283                 function parseResponse($data='')\r
1284                 {\r
1285                         global $_xh,$xmlrpcerr,$xmlrpcstr;\r
1286                         global $xmlrpc_defencoding, $xmlrpc_internalencoding;\r
1287 \r
1288                         $hdrfnd = 0;\r
1289                         if($this->debug)\r
1290                         {\r
1291                                 //by maHo, replaced htmlspecialchars with htmlentities\r
1292                                 print "<PRE>---GOT---\n" . htmlentities($data) . "\n---END---\n</PRE>";\r
1293                         }\r
1294 \r
1295                         if($data == '')\r
1296                         {\r
1297                                 error_log('No response received from server.');\r
1298                                 $r = new xmlrpcresp(0, $xmlrpcerr['no_data'], $xmlrpcstr['no_data']);\r
1299                                 return $r;\r
1300                         }\r
1301                         // see if we got an HTTP 200 OK, else bomb\r
1302                         // but only do this if we're using the HTTP protocol.\r
1303                         if(ereg("^HTTP",$data))\r
1304                         {\r
1305                                 // Strip HTTP 1.1 100 Continue header if present\r
1306                                 while (ereg('^HTTP/1.1 1[0-9]{2}', $data))\r
1307                                 {\r
1308                                         $pos = strpos($data, 'HTTP', 12);\r
1309                                         // server sent a Continue header without any (valid) content following...\r
1310                                         // give the client a chance to know it\r
1311                                         if (!$pos && !is_int($pos)) // works fine in php 3, 4 and 5\r
1312                                                 break;\r
1313                                         $data = substr($data, $pos);\r
1314                                 }\r
1315                                 if (!ereg("^HTTP/[0-9\\.]+ 200 ", $data))\r
1316                                 {\r
1317                                         $errstr= substr($data, 0, strpos($data, "\n")-1);\r
1318                                         error_log('HTTP error, got response: ' .$errstr);\r
1319                                         $r=new xmlrpcresp(0, $xmlrpcerr['http_error'], $xmlrpcstr['http_error']. ' (' . $errstr . ')');\r
1320                                         return $r;\r
1321                                 }\r
1322                         }\r
1323                         $parser = xml_parser_create($xmlrpc_defencoding);\r
1324 \r
1325                         // G. Giunta 2004/04/06\r
1326                         // Clean up the accumulator, or it will grow indefinitely long\r
1327                         // if making xmlrpc calls for a while\r
1328                         $_xh=array();\r
1329                         $_xh[$parser]=array();\r
1330                         $_xh[$parser]['headers'] = array();\r
1331 \r
1332                         // separate HTTP headers from data\r
1333                         if (ereg("^HTTP", $data))\r
1334                         {\r
1335                                 // be tolerant to usage of \n instead of \r\n to separate headers and data\r
1336                                 // (even though it is not valid http)\r
1337                                 $pos = strpos($data,"\r\n\r\n");\r
1338                                 if($pos || is_int($pos))\r
1339                                         $bd = $pos+4;\r
1340                                 else\r
1341                                 {\r
1342                                         $pos = strpos($data,"\n\n");\r
1343                                         if($pos || is_int($pos))\r
1344                                                 $bd = $pos+2;\r
1345                                         else\r
1346                                         {\r
1347                                                 // No separation between response headers and body: fault?\r
1348                                                 $bd = 0;\r
1349                                         }\r
1350                                 }\r
1351                                 // be tolerant to line endings, and extra empty lines\r
1352                                 $ar = split("\r?\n", trim(substr($data, 0, $pos)));\r
1353                                 while (list(,$line) = @each($ar))\r
1354                                 {\r
1355                                         // take care of multi-line headers\r
1356                                         $arr = explode(':',$line);\r
1357                                         if(count($arr) > 1)\r
1358                                         {\r
1359                                                 $header_name = trim($arr[0]);\r
1360                                                 // TO DO: some headers (the ones that allow a CSV list of values)\r
1361                                                 // do allow many values to be passed using multiple header lines.\r
1362                                                 // We should add content to $_xh[$parser]['headers'][$header_name]\r
1363                                                 // instead of replacing it for those...\r
1364                                                 $_xh[$parser]['headers'][$header_name] = $arr[1];\r
1365                                                 for ($i = 2; $i < count($arr); $i++)\r
1366                                                 {\r
1367                                                         $_xh[$parser]['headers'][$header_name] .= ':'.$arr[$i];\r
1368                                                 } // while\r
1369                                                 $_xh[$parser]['headers'][$header_name] = trim($_xh[$parser]['headers'][$header_name]);\r
1370                                         } else if (isset($header_name))\r
1371                                         {\r
1372                                                 $_xh[$parser]['headers'][$header_name] .= ' ' . trim($line);\r
1373                                         }\r
1374                                 }\r
1375                                 $data = substr($data, $bd);\r
1376 \r
1377                                 if ($this->debug && count($_xh[$parser]['headers']))\r
1378                                 {\r
1379                                         print '<PRE>';\r
1380                                         //foreach ($_xh[$parser]['headers'] as $header)\r
1381                                         @reset($_xh[$parser]['headers']);\r
1382                                         while(list($header, $value) = @each($_xh[$parser]['headers']))\r
1383                                         {\r
1384                                                 print "HEADER: $header: $value\n";\r
1385                                         }\r
1386                                         print "</PRE>\n";\r
1387                                 }\r
1388                         }\r
1389 \r
1390                         // be tolerant of extra whitespace in response body\r
1391                         $data = trim($data);\r
1392 \r
1393                         // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts)\r
1394                         // idea from Luca Mariano <luca.mariano@email.it> originally in PEARified version of the lib\r
1395                         $bd = false;\r
1396                         $pos = strpos($data, "</methodResponse>");\r
1397                         while ($pos || is_int($pos))\r
1398                         {\r
1399                                 $bd = $pos+17;\r
1400                                 $pos = strpos($data, "</methodResponse>", $bd);\r
1401                         }\r
1402                         if ($bd)\r
1403                                 $data = substr($data, 0, $bd);\r
1404 \r
1405                         $_xh[$parser]['st']='';\r
1406                         $_xh[$parser]['cm']=0;\r
1407                         $_xh[$parser]['isf']=0;\r
1408                         $_xh[$parser]['ac']='';\r
1409                         $_xh[$parser]['qt']='';\r
1410 \r
1411                         xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);\r
1412                         // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell\r
1413                         // the xml parser to give us back data in the expected charset\r
1414                         xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $xmlrpc_internalencoding);\r
1415 \r
1416                         xml_set_element_handler($parser, 'xmlrpc_se', 'xmlrpc_ee');\r
1417                         xml_set_character_data_handler($parser, 'xmlrpc_cd');\r
1418                         xml_set_default_handler($parser, 'xmlrpc_dh');\r
1419                         //$xmlrpc_value=new xmlrpcval;\r
1420 \r
1421                         if (!xml_parse($parser, $data, sizeof($data)))\r
1422                         {\r
1423                                 // thanks to Peter Kocks <peter.kocks@baygate.com>\r
1424                                 if((xml_get_current_line_number($parser)) == 1)\r
1425                                 {\r
1426                                         $errstr = 'XML error at line 1, check URL';\r
1427                                 }\r
1428                                 else\r
1429                                 {\r
1430                                         $errstr = sprintf('XML error: %s at line %d',\r
1431                                                 xml_error_string(xml_get_error_code($parser)),\r
1432                                                 xml_get_current_line_number($parser));\r
1433                                 }\r
1434                                 error_log($errstr);\r
1435                                 $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return'].' ('.$errstr.')');\r
1436                                 xml_parser_free($parser);\r
1437                                 if ($this->debug)\r
1438                                         echo $errstr;\r
1439                                 $r->hdrs = $_xh[$parser]['headers'];\r
1440                                 return $r;\r
1441                         }\r
1442                         xml_parser_free($parser);\r
1443                         if ($this->debug)\r
1444                         {\r
1445                                 print "<PRE>---EVALING---[" .\r
1446                                 strlen($_xh[$parser]['st']) . " chars]---\n" .\r
1447                                 htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>";\r
1448                         }\r
1449                         if (strlen($_xh[$parser]['st'])==0)\r
1450                         {\r
1451                                 // then something odd has happened\r
1452                                 // and it's time to generate a client side error\r
1453                                 // indicating something odd went on\r
1454                                 $r=new xmlrpcresp(0, $xmlrpcerr['invalid_return'],\r
1455                                 $xmlrpcstr['invalid_return']);\r
1456                         }\r
1457                         else\r
1458                         {\r
1459                                 $allOK=0;\r
1460                                 @eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;');\r
1461                                 if (!$allOK)\r
1462                                 {\r
1463                                         $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']);\r
1464                                 }\r
1465                                 else\r
1466                                 if ($_xh[$parser]['isf'])\r
1467                                 {\r
1468                                         $errno_v = $v->structmem('faultCode');\r
1469                                         $errstr_v = $v->structmem('faultString');\r
1470                                         $errno = $errno_v->scalarval();\r
1471 \r
1472                                         if ($errno == 0)\r
1473                                         {\r
1474                                                 // FAULT returned, errno needs to reflect that\r
1475                                                 $errno = -1;\r
1476                                         }\r
1477 \r
1478                                         $r = new xmlrpcresp($v, $errno, $errstr_v->scalarval());\r
1479                                 }\r
1480                                 else\r
1481                                 {\r
1482                                         $r=new xmlrpcresp($v);\r
1483                                 }\r
1484                         }\r
1485 \r
1486                         $r->hdrs = $_xh[$parser]['headers'];\r
1487                         return $r;\r
1488                 }\r
1489         }\r
1490 \r
1491         class xmlrpcval\r
1492         {\r
1493                 var $me=array();\r
1494                 var $mytype=0;\r
1495 \r
1496                 function xmlrpcval($val=-1, $type='')\r
1497                 {\r
1498                         global $xmlrpcTypes;\r
1499                         $this->me=array();\r
1500                         $this->mytype=0;\r
1501                         if ($val!=-1 || !is_int($val) || $type!='')\r
1502                         {\r
1503                                 if ($type=='')\r
1504                                 {\r
1505                                         $type='string';\r
1506                                 }\r
1507                                 if ($xmlrpcTypes[$type]==1)\r
1508                                 {\r
1509                                         $this->addScalar($val,$type);\r
1510                                 }\r
1511                                 elseif ($xmlrpcTypes[$type]==2)\r
1512                                 {\r
1513                                         $this->addArray($val);\r
1514                                 }\r
1515                                 elseif ($xmlrpcTypes[$type]==3)\r
1516                                 {\r
1517                                         $this->addStruct($val);\r
1518                                 }\r
1519                         }\r
1520                 }\r
1521 \r
1522                 function addScalar($val, $type='string')\r
1523                 {\r
1524                         global $xmlrpcTypes, $xmlrpcBoolean;\r
1525 \r
1526                         if ($this->mytype==1)\r
1527                         {\r
1528                                 echo '<B>xmlrpcval</B>: scalar can have only one value<BR>';\r
1529                                 return 0;\r
1530                         }\r
1531                         $typeof=$xmlrpcTypes[$type];\r
1532                         if ($typeof!=1)\r
1533                         {\r
1534                                 echo '<B>xmlrpcval</B>: not a scalar type (${typeof})<BR>';\r
1535                                 return 0;\r
1536                         }\r
1537 \r
1538                         if ($type==$xmlrpcBoolean)\r
1539                         {\r
1540                                 if (strcasecmp($val,'true')==0 || $val==1 || ($val==true && strcasecmp($val,'false')))\r
1541                                 {\r
1542                                         $val=1;\r
1543                                 }\r
1544                                 else\r
1545                                 {\r
1546                                         $val=0;\r
1547                                 }\r
1548                         }\r
1549 \r
1550                         if ($this->mytype==2)\r
1551                         {\r
1552                                 // we're adding to an array here\r
1553                                 $ar=$this->me['array'];\r
1554                                 $ar[]=new xmlrpcval($val, $type);\r
1555                                 $this->me['array']=$ar;\r
1556                         }\r
1557                         else\r
1558                         {\r
1559                                 // a scalar, so set the value and remember we're scalar\r
1560                                 $this->me[$type]=$val;\r
1561                                 $this->mytype=$typeof;\r
1562                         }\r
1563                         return 1;\r
1564                 }\r
1565 \r
1566                 function addArray($vals)\r
1567                 {\r
1568                         global $xmlrpcTypes;\r
1569                         if ($this->mytype!=0)\r
1570                         {\r
1571                                 echo '<B>xmlrpcval</B>: already initialized as a [' . $this->kindOf() . ']<BR>';\r
1572                                 return 0;\r
1573                         }\r
1574 \r
1575                         $this->mytype=$xmlrpcTypes['array'];\r
1576                         $this->me['array']=$vals;\r
1577                         return 1;\r
1578                 }\r
1579 \r
1580                 function addStruct($vals)\r
1581                 {\r
1582                         global $xmlrpcTypes;\r
1583                         if ($this->mytype!=0)\r
1584                         {\r
1585                                 echo '<B>xmlrpcval</B>: already initialized as a [' . $this->kindOf() . ']<BR>';\r
1586                                 return 0;\r
1587                         }\r
1588                         $this->mytype=$xmlrpcTypes['struct'];\r
1589                         $this->me['struct']=$vals;\r
1590                         return 1;\r
1591                 }\r
1592 \r
1593                 function dump($ar)\r
1594                 {\r
1595                         reset($ar);\r
1596                         while ( list( $key, $val ) = each( $ar ) )\r
1597                         {\r
1598                                 echo "$key => $val<br>";\r
1599                                 if ($key == 'array')\r
1600                                 {\r
1601                                         while ( list( $key2, $val2 ) = each( $val ) )\r
1602                                         {\r
1603                                                 echo "-- $key2 => $val2<br>";\r
1604                                         }\r
1605                                 }\r
1606                         }\r
1607                 }\r
1608 \r
1609                 function kindOf()\r
1610                 {\r
1611                         switch($this->mytype)\r
1612                         {\r
1613                                 case 3:\r
1614                                         return 'struct';\r
1615                                         break;\r
1616                                 case 2:\r
1617                                         return 'array';\r
1618                                         break;\r
1619                                 case 1:\r
1620                                         return 'scalar';\r
1621                                         break;\r
1622                                 default:\r
1623                                         return 'undef';\r
1624                         }\r
1625                 }\r
1626 \r
1627                 function serializedata($typ, $val)\r
1628                 {\r
1629                         $rs='';\r
1630                         global $xmlrpcTypes, $xmlrpcBase64, $xmlrpcString,\r
1631                         $xmlrpcBoolean;\r
1632                         switch(@$xmlrpcTypes[$typ])\r
1633                         {\r
1634                                 case 3:\r
1635                                         // struct\r
1636                                         $rs.="<struct>\n";\r
1637                                         reset($val);\r
1638                                         while(list($key2, $val2)=each($val))\r
1639                                         {\r
1640                                                 $rs.="<member><name>${key2}</name>\n";\r
1641                                                 $rs.=$this->serializeval($val2);\r
1642                                                 $rs.="</member>\n";\r
1643                                         }\r
1644                                         $rs.='</struct>';\r
1645                                         break;\r
1646                                 case 2:\r
1647                                         // array\r
1648                                         $rs.="<array>\n<data>\n";\r
1649                                         for($i=0; $i<sizeof($val); $i++)\r
1650                                         {\r
1651                                                 $rs.=$this->serializeval($val[$i]);\r
1652                                         }\r
1653                                         $rs.="</data>\n</array>";\r
1654                                         break;\r
1655                                 case 1:\r
1656                                         switch ($typ)\r
1657                                         {\r
1658                                                 case $xmlrpcBase64:\r
1659                                                         $rs.="<${typ}>" . base64_encode($val) . "</${typ}>";\r
1660                                                         break;\r
1661                                                 case $xmlrpcBoolean:\r
1662                                                         $rs.="<${typ}>" . ($val ? '1' : '0') . "</${typ}>";\r
1663                                                         break;\r
1664                                                 case $xmlrpcString:\r
1665                                                         // G. Giunta 2005/2/13: do NOT use htmlentities, since\r
1666                                                         // it will produce named html entities, which are invalid xml\r
1667                                                         // $rs.="<${typ}>" . xmlrpc_encode_entitites($val). "</${typ}>";\r
1668                                                         // $rs.="<${typ}>" . htmlentities($val). "</${typ}>";\r
1669                                                         \r
1670                                                         // N. Leenheer 2005/6/30: Use CDATA instead... \r
1671                                                         $rs.="<${typ}><![CDATA[" . $val. "]]></${typ}>";\r
1672                                                         break;\r
1673                                                 default:\r
1674                                                         $rs.="<${typ}>${val}</${typ}>";\r
1675                                         }\r
1676                                         break;\r
1677                                 default:\r
1678                                         break;\r
1679                         }\r
1680                         return $rs;\r
1681                 }\r
1682 \r
1683                 function serialize()\r
1684                 {\r
1685                         return $this->serializeval($this);\r
1686                 }\r
1687 \r
1688                 function serializeval($o)\r
1689                 {\r
1690                         //global $xmlrpcTypes;\r
1691                         $rs='';\r
1692                         $ar=$o->me;\r
1693                         reset($ar);\r
1694                         list($typ, $val) = each($ar);\r
1695                         $rs.='<value>';\r
1696                         $rs.=$this->serializedata($typ, $val);\r
1697                         $rs.="</value>\n";\r
1698                         return $rs;\r
1699                 }\r
1700 \r
1701                 function structmem($m)\r
1702                 {\r
1703                         $nv=$this->me['struct'][$m];\r
1704                         return $nv;\r
1705                 }\r
1706 \r
1707                 function structreset()\r
1708                 {\r
1709                         reset($this->me['struct']);\r
1710                 }\r
1711 \r
1712                 function structeach()\r
1713                 {\r
1714                         return each($this->me['struct']);\r
1715                 }\r
1716 \r
1717                 function getval()\r
1718                 {\r
1719                         // UNSTABLE\r
1720                         global $xmlrpcBoolean, $xmlrpcBase64;\r
1721                         reset($this->me);\r
1722                         list($a,$b)=each($this->me);\r
1723                         // contributed by I Sofer, 2001-03-24\r
1724                         // add support for nested arrays to scalarval\r
1725                         // i've created a new method here, so as to\r
1726                         // preserve back compatibility\r
1727 \r
1728                         if (is_array($b))\r
1729                         {\r
1730                                 @reset($b);\r
1731                                 while(list($id,$cont) = @each($b))\r
1732                                 {\r
1733                                         $b[$id] = $cont->scalarval();\r
1734                                 }\r
1735                         }\r
1736 \r
1737                         // add support for structures directly encoding php objects\r
1738                         if (is_object($b))\r
1739                         {\r
1740                                 $t = get_object_vars($b);\r
1741                                 @reset($t);\r
1742                                 while(list($id,$cont) = @each($t))\r
1743                                 {\r
1744                                         $t[$id] = $cont->scalarval();\r
1745                                 }\r
1746                                 @reset($t);\r
1747                                 while(list($id,$cont) = @each($t))\r
1748                                 {\r
1749                                         eval('$b->'.$id.' = $cont;');\r
1750                                 }\r
1751                         }\r
1752                         // end contrib\r
1753                         return $b;\r
1754                 }\r
1755 \r
1756                 function scalarval()\r
1757                 {\r
1758                         //global $xmlrpcBoolean, $xmlrpcBase64;\r
1759                         reset($this->me);\r
1760                         list($a,$b)=each($this->me);\r
1761                         return $b;\r
1762                 }\r
1763 \r
1764                 function scalartyp()\r
1765                 {\r
1766                         global $xmlrpcI4, $xmlrpcInt;\r
1767                         reset($this->me);\r
1768                         list($a,$b)=each($this->me);\r
1769                         if ($a==$xmlrpcI4)\r
1770                         {\r
1771                                 $a=$xmlrpcInt;\r
1772                         }\r
1773                         return $a;\r
1774                 }\r
1775 \r
1776                 function arraymem($m)\r
1777                 {\r
1778                         $nv=$this->me['array'][$m];\r
1779                         return $nv;\r
1780                 }\r
1781 \r
1782                 function arraysize()\r
1783                 {\r
1784                         reset($this->me);\r
1785                         list($a,$b)=each($this->me);\r
1786                         return sizeof($b);\r
1787                 }\r
1788         }\r
1789 \r
1790         // date helpers\r
1791         function iso8601_encode($timet, $utc=0)\r
1792         {\r
1793                 // return an ISO8601 encoded string\r
1794                 // really, timezones ought to be supported\r
1795                 // but the XML-RPC spec says:\r
1796                 //\r
1797                 // "Don't assume a timezone. It should be specified by the server in its\r
1798                 // documentation what assumptions it makes about timezones."\r
1799                 // \r
1800                 // these routines always assume localtime unless \r
1801                 // $utc is set to 1, in which case UTC is assumed\r
1802                 // and an adjustment for locale is made when encoding\r
1803                 if (!$utc)\r
1804                 {\r
1805                         $t=strftime("%Y%m%dT%H:%M:%S", $timet);\r
1806                 }\r
1807                 else\r
1808                 {\r
1809                         if (function_exists('gmstrftime'))\r
1810                         {\r
1811                                 // gmstrftime doesn't exist in some versions\r
1812                                 // of PHP\r
1813                                 $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet);\r
1814                         }\r
1815                         else\r
1816                         {\r
1817                                 $t=strftime("%Y%m%dT%H:%M:%S", $timet-date('Z'));\r
1818                         }\r
1819                 }\r
1820                 return $t;\r
1821         }\r
1822 \r
1823         function iso8601_decode($idate, $utc=0)\r
1824         {\r
1825                 // return a timet in the localtime, or UTC\r
1826                 $t=0;\r
1827                 if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", $idate, $regs))\r
1828                 {\r
1829                         if ($utc)\r
1830                         {\r
1831                                 $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);\r
1832                         }\r
1833                         else\r
1834                         {\r
1835                                 $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);\r
1836                         }\r
1837                 } \r
1838                 return $t;\r
1839         }\r
1840 \r
1841         /****************************************************************\r
1842         * xmlrpc_decode takes a message in PHP xmlrpc object format and *\r
1843         * tranlates it into native PHP types.                           *\r
1844         *                                                               *\r
1845         * author: Dan Libby (dan@libby.com)                             *\r
1846         ****************************************************************/\r
1847         function php_xmlrpc_decode($xmlrpc_val)\r
1848         {\r
1849                 $kind = $xmlrpc_val->kindOf();\r
1850 \r
1851                 if($kind == 'scalar')\r
1852                 {\r
1853                         return $xmlrpc_val->scalarval();\r
1854                 }\r
1855                 elseif($kind == 'array')\r
1856                 {\r
1857                         $size = $xmlrpc_val->arraysize();\r
1858                         $arr = array();\r
1859 \r
1860                         for($i = 0; $i < $size; $i++)\r
1861                         {\r
1862                                 $arr[] = php_xmlrpc_decode($xmlrpc_val->arraymem($i));\r
1863                         }\r
1864                         return $arr;\r
1865                 }\r
1866                 elseif($kind == 'struct')\r
1867                 {\r
1868                         $xmlrpc_val->structreset();\r
1869                         $arr = array();\r
1870 \r
1871                         while(list($key,$value)=$xmlrpc_val->structeach())\r
1872                         {\r
1873                                 $arr[$key] = php_xmlrpc_decode($value);\r
1874                         }\r
1875                         return $arr;\r
1876                 }\r
1877         }\r
1878 \r
1879         if(function_exists('xmlrpc_decode'))\r
1880         {\r
1881                 define('XMLRPC_EPI_ENABLED','1');\r
1882         }\r
1883         else\r
1884         {\r
1885                 define('XMLRPC_EPI_ENABLED','0');\r
1886                 function xmlrpc_decode($xmlrpc_val)\r
1887                 {\r
1888                         $kind = $xmlrpc_val->kindOf();\r
1889 \r
1890                         if($kind == 'scalar')\r
1891                         {\r
1892                                 return $xmlrpc_val->scalarval();\r
1893                         }\r
1894                         elseif($kind == 'array')\r
1895                         {\r
1896                                 $size = $xmlrpc_val->arraysize();\r
1897                                 $arr = array();\r
1898 \r
1899                                 for($i = 0; $i < $size; $i++)\r
1900                                 {\r
1901                                         $arr[]=xmlrpc_decode($xmlrpc_val->arraymem($i));\r
1902                                 }\r
1903                                 return $arr;\r
1904                         }\r
1905                         elseif($kind == 'struct')\r
1906                         {\r
1907                                 $xmlrpc_val->structreset();\r
1908                                 $arr = array();\r
1909 \r
1910                                 while(list($key,$value)=$xmlrpc_val->structeach())\r
1911                                 {\r
1912                                         $arr[$key] = xmlrpc_decode($value);\r
1913                                 }\r
1914                                 return $arr;\r
1915                         }\r
1916                 }\r
1917         }\r
1918 \r
1919         /****************************************************************\r
1920         * xmlrpc_encode takes native php types and encodes them into    *\r
1921         * xmlrpc PHP object format.                                     *\r
1922         * BUG: All sequential arrays are turned into structs.  I don't  *\r
1923         * know of a good way to determine if an array is sequential     *\r
1924         * only.                                                         *\r
1925         *                                                               *\r
1926         * feature creep -- could support more types via optional type   *\r
1927         * argument.                                                     *\r
1928         *                                                               *\r
1929         * author: Dan Libby (dan@libby.com)                             *\r
1930         ****************************************************************/\r
1931         function php_xmlrpc_encode($php_val)\r
1932         {\r
1933                 global $xmlrpcInt;\r
1934                 global $xmlrpcDouble;\r
1935                 global $xmlrpcString;\r
1936                 global $xmlrpcArray;\r
1937                 global $xmlrpcStruct;\r
1938                 global $xmlrpcBoolean;\r
1939 \r
1940                 $type = gettype($php_val);\r
1941                 $xmlrpc_val = new xmlrpcval;\r
1942 \r
1943                 switch($type)\r
1944                 {\r
1945                         case 'array':\r
1946                         case 'object':\r
1947                                 $arr = array();\r
1948                                 while (list($k,$v) = each($php_val))\r
1949                                 {\r
1950                                         $arr[$k] = php_xmlrpc_encode($v);\r
1951                                 }\r
1952                                 $xmlrpc_val->addStruct($arr);\r
1953                                 break;\r
1954                         case 'integer':\r
1955                                 $xmlrpc_val->addScalar($php_val, $xmlrpcInt);\r
1956                                 break;\r
1957                         case 'double':\r
1958                                 $xmlrpc_val->addScalar($php_val, $xmlrpcDouble);\r
1959                                 break;\r
1960                         case 'string':\r
1961                                 $xmlrpc_val->addScalar($php_val, $xmlrpcString);\r
1962                                 break;\r
1963                                 // <G_Giunta_2001-02-29>\r
1964                                 // Add support for encoding/decoding of booleans, since they are supported in PHP\r
1965                         case 'boolean':\r
1966                                 $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean);\r
1967                                 break;\r
1968                                 // </G_Giunta_2001-02-29>\r
1969                         // catch "resource", "NULL", "user function", "unknown type"\r
1970                         //case 'unknown type':\r
1971                         default:\r
1972                                 // giancarlo pinerolo <ping@alt.it>\r
1973                                 // it has to return \r
1974                                 // an empty object in case (which is already\r
1975                                 // at this point), not a boolean. \r
1976                                 break;\r
1977                         }\r
1978                         return $xmlrpc_val;\r
1979         }\r
1980 \r
1981         if(XMLRPC_EPI_ENABLED == '0')\r
1982         {\r
1983                 function xmlrpc_encode($php_val)\r
1984                 {\r
1985                         global $xmlrpcInt;\r
1986                         global $xmlrpcDouble;\r
1987                         global $xmlrpcString;\r
1988                         global $xmlrpcArray;\r
1989                         global $xmlrpcStruct;\r
1990                         global $xmlrpcBoolean;\r
1991 \r
1992                         $type = gettype($php_val);\r
1993                         $xmlrpc_val = new xmlrpcval;\r
1994 \r
1995                         switch($type)\r
1996                         {\r
1997                                 case 'array':\r
1998                                 case 'object':\r
1999                                         $arr = array();\r
2000                                         while (list($k,$v) = each($php_val))\r
2001                                         {\r
2002                                                 $arr[$k] = xmlrpc_encode($v);\r
2003                                         }\r
2004                                         $xmlrpc_val->addStruct($arr);\r
2005                                         break;\r
2006                                 case 'integer':\r
2007                                         $xmlrpc_val->addScalar($php_val, $xmlrpcInt);\r
2008                                         break;\r
2009                                 case 'double':\r
2010                                         $xmlrpc_val->addScalar($php_val, $xmlrpcDouble);\r
2011                                         break;\r
2012                                 case 'string':\r
2013                                         $xmlrpc_val->addScalar($php_val, $xmlrpcString);\r
2014                                         break;\r
2015                                         // <G_Giunta_2001-02-29>\r
2016                                         // Add support for encoding/decoding of booleans, since they are supported in PHP\r
2017                                 case 'boolean':\r
2018                                         $xmlrpc_val->addScalar($php_val, $xmlrpcBoolean);\r
2019                                         break;\r
2020                                         // </G_Giunta_2001-02-29>\r
2021                                 //case 'unknown type':\r
2022                                 default:\r
2023                                         // giancarlo pinerolo <ping@alt.it>\r
2024                                         // it has to return \r
2025                                         // an empty object in case (which is already\r
2026                                         // at this point), not a boolean. \r
2027                                         break;\r
2028                         }\r
2029                         return $xmlrpc_val;\r
2030                 }\r
2031         }\r
2032 ?>\r