/[cvs]/nfo/php/libs/net.php.pear/XML/RPC/RPC.php
ViewVC logotype

Annotation of /nfo/php/libs/net.php.pear/XML/RPC/RPC.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Wed Oct 9 00:45:02 2002 UTC (21 years, 11 months ago) by cvsjoko
Branch: MAIN
no message

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

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed