OSDN Git Service

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