/[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.4 - (hide annotations)
Wed Feb 5 22:10:59 2003 UTC (21 years, 7 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +6 -2 lines
- removed previous patch
+ fixed problem ("remote side is not available leads to fatal php error") elsewhere: 'sendPayloadHTTP10' now doesn't continue if (socket-) connection fails

1 cvsjoko 1.1 <?php
2     // by Edd Dumbill (C) 1999-2001
3     // <edd@usefulinc.com>
4 joko 1.4 // $Id: RPC.php,v 1.3 2002/10/28 04:21:48 cvsjoko Exp $
5 cvsjoko 1.1
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 cvsjoko 1.2 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
16 cvsjoko 1.1 // 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 cvsjoko 1.2 $GLOBALS['XML_RPC_erruser']=800;
76 cvsjoko 1.1 // 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 cvsjoko 1.2 $i=0;
103 cvsjoko 1.1 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 cvsjoko 1.2 if ($i==0)
110     $op=$top[$i];
111 cvsjoko 1.1 else
112     $op.="&" . $top[$i];
113     }
114 cvsjoko 1.2
115 cvsjoko 1.1 $i++;
116     }
117     return $op;
118     }
119    
120    
121     function XML_RPC_lookup_entity($ent)
122     {
123     global $XML_RPC_entities;
124 cvsjoko 1.2
125     if ($XML_RPC_entities[strtolower($ent)])
126 cvsjoko 1.1 return $XML_RPC_entities[strtolower($ent)];
127 cvsjoko 1.2
128 cvsjoko 1.1 if (ereg("^#([0-9]+)$", $ent, $regs))
129     return chr($regs[1]);
130 cvsjoko 1.2
131 cvsjoko 1.1 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 cvsjoko 1.2
139 cvsjoko 1.1 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 cvsjoko 1.2 // this means if we get an empty array we'll
146 cvsjoko 1.1 // 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 cvsjoko 1.2 $XML_RPC_xh[$parser]['st'].="new XML_RPC_Value(";
160 cvsjoko 1.1 $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 cvsjoko 1.2
169 cvsjoko 1.1 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 cvsjoko 1.2
178 cvsjoko 1.1 if ($name=="DATETIME.ISO8601" || $name=="STRING") {
179 cvsjoko 1.2 $XML_RPC_xh[$parser]['qt']=1;
180    
181 cvsjoko 1.1 if ($name=="DATETIME.ISO8601")
182     $XML_RPC_xh[$parser]['vt']=$XML_RPC_DateTime;
183 cvsjoko 1.2
184 cvsjoko 1.1 } 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 cvsjoko 1.2
194 cvsjoko 1.1 case "MEMBER":
195     $XML_RPC_xh[$parser]['ac']="";
196     break;
197     default:
198     break;
199     }
200 cvsjoko 1.2
201 cvsjoko 1.1 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 cvsjoko 1.2
216     $XML_RPC_xh[$parser]['st'].=")";
217 cvsjoko 1.1 $XML_RPC_xh[$parser]['vt']=strtolower($name);
218     $XML_RPC_xh[$parser]['cm']--;
219     break;
220 cvsjoko 1.2
221 cvsjoko 1.1 case "NAME":
222     $XML_RPC_xh[$parser]['st'].= $XML_RPC_xh[$parser]['ac'] . "' => ";
223     break;
224 cvsjoko 1.2
225 cvsjoko 1.1 case "BOOLEAN":
226     // special case here: we translate boolean 1 or 0 into PHP
227     // constants true or false
228 cvsjoko 1.2 if ($XML_RPC_xh[$parser]['ac']=='1')
229 cvsjoko 1.1 $XML_RPC_xh[$parser]['ac']="true";
230 cvsjoko 1.2 else
231 cvsjoko 1.1 $XML_RPC_xh[$parser]['ac']="false";
232 cvsjoko 1.2
233 cvsjoko 1.1 $XML_RPC_xh[$parser]['vt']=strtolower($name);
234     // Drop through intentionally.
235 cvsjoko 1.2
236 cvsjoko 1.1 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 cvsjoko 1.2 $XML_RPC_xh[$parser]['st'].="\"". $XML_RPC_xh[$parser]['ac'] . "\"";
245 cvsjoko 1.1 } else if ($XML_RPC_xh[$parser]['qt']==2) {
246 cvsjoko 1.2 $XML_RPC_xh[$parser]['st'].="base64_decode('". $XML_RPC_xh[$parser]['ac'] . "')";
247 cvsjoko 1.1 } 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 cvsjoko 1.2 $XML_RPC_xh[$parser]['st'].="ERROR_NON_NUMERIC_FOUND";
257 cvsjoko 1.1 } else {
258     // it's ok, add it on
259     $XML_RPC_xh[$parser]['st'].=$XML_RPC_xh[$parser]['ac'];
260     }
261     }
262 cvsjoko 1.2
263 cvsjoko 1.1 $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 cvsjoko 1.2
267 cvsjoko 1.1 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 cvsjoko 1.2
272     $XML_RPC_xh[$parser]['st'].="\"". $XML_RPC_xh[$parser]['ac'] . "\"";
273 cvsjoko 1.1 }
274 cvsjoko 1.2
275 cvsjoko 1.1 // 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 cvsjoko 1.2
284 cvsjoko 1.1 case "MEMBER":
285     $XML_RPC_xh[$parser]['ac']=""; $XML_RPC_xh[$parser]['qt']=0;
286     break;
287 cvsjoko 1.2
288 cvsjoko 1.1 case "DATA":
289     $XML_RPC_xh[$parser]['ac']=""; $XML_RPC_xh[$parser]['qt']=0;
290     break;
291 cvsjoko 1.2
292 cvsjoko 1.1 case "PARAM":
293     $XML_RPC_xh[$parser]['params'][]=$XML_RPC_xh[$parser]['st'];
294     break;
295 cvsjoko 1.2
296 cvsjoko 1.1 case "METHODNAME":
297     $XML_RPC_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", "", $XML_RPC_xh[$parser]['ac']);
298     break;
299 cvsjoko 1.2
300 cvsjoko 1.1 case "BOOLEAN":
301     // special case here: we translate boolean 1 or 0 into PHP
302     // constants true or false
303 cvsjoko 1.2 if ($XML_RPC_xh[$parser]['ac']=='1')
304 cvsjoko 1.1 $XML_RPC_xh[$parser]['ac']="true";
305 cvsjoko 1.2 else
306 cvsjoko 1.1 $XML_RPC_xh[$parser]['ac']="false";
307 cvsjoko 1.2
308 cvsjoko 1.1 $XML_RPC_xh[$parser]['vt']=strtolower($name);
309     break;
310 cvsjoko 1.2
311 cvsjoko 1.1 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 cvsjoko 1.2 {
323 cvsjoko 1.1 global $XML_RPC_xh, $XML_RPC_backslash;
324    
325     //if (ereg("^[\n\r \t]+$", $data)) return;
326     // print "adding [${data}]\n";
327 cvsjoko 1.2
328 cvsjoko 1.1 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 cvsjoko 1.2
332     if ($XML_RPC_xh[$parser]['lv']==1) {
333 cvsjoko 1.1 // if we've found text and we're just in a <value> then
334     // turn quoting on, as this will be a string
335 cvsjoko 1.2 $XML_RPC_xh[$parser]['qt']=1;
336 cvsjoko 1.1 // and say we've found a value
337 cvsjoko 1.2 $XML_RPC_xh[$parser]['lv']=2;
338 cvsjoko 1.1 }
339 cvsjoko 1.2
340 cvsjoko 1.1 // 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 cvsjoko 1.2 if ($XML_RPC_xh[$parser]['lv']==1) {
354     $XML_RPC_xh[$parser]['qt']=1;
355     $XML_RPC_xh[$parser]['lv']=2;
356 cvsjoko 1.1 }
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 cvsjoko 1.2
375     function XML_RPC_Client($path, $server, $port = 80,
376     $proxy = '', $proxy_port = 8080,
377     $proxy_user = '', $proxy_pass = '')
378 cvsjoko 1.1 {
379     $this->port=$port;
380     $this->server=$server;
381     $this->path=$path;
382 cvsjoko 1.2 $this->proxy = $proxy;
383     $this->proxy_port = $proxy_port;
384     $this->proxy_user = $proxy_user;
385     $this->proxy_pass = $proxy_pass;
386 cvsjoko 1.1 }
387    
388     function setDebug($in)
389     {
390 cvsjoko 1.2 if ($in) {
391 cvsjoko 1.1 $this->debug=1;
392     } else {
393     $this->debug=0;
394     }
395     }
396    
397     function setCredentials($u, $p)
398     {
399     $this->username=$u;
400     $this->password=$p;
401     }
402    
403     function send($msg, $timeout=0)
404     {
405     // where msg is an xmlrpcmsg
406     $msg->debug=$this->debug;
407     return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
408 cvsjoko 1.2 $timeout, $this->username,
409 cvsjoko 1.1 $this->password);
410     }
411    
412     function sendPayloadHTTP10($msg, $server, $port, $timeout=0,
413     $username="", $password="")
414     {
415     // If we're using a proxy open a socket to the proxy server instead to the xml-rpc server
416     if($this->proxy){
417     if($timeout > 0) {
418     $fp=fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr, $timeout);
419     }
420     else {
421 cvsjoko 1.2 $fp=fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr);
422 cvsjoko 1.1 }
423 cvsjoko 1.2 }
424 cvsjoko 1.1 else {
425     if($timeout > 0) {
426     $fp=fsockopen($server, $port, $this->errno, $this->errstr, $timeout);
427     }
428     else {
429 cvsjoko 1.2 $fp=fsockopen($server, $port, $this->errno, $this->errstr);
430 cvsjoko 1.1 }
431     }
432    
433     if(!$fp && $this->proxy) {
434     PEAR::raiseError("Connection to proxy server ".$this->proxy.":".$this->proxy_port." failed");
435 joko 1.4 $this->errstr="Connect error";
436     return 0;
437 cvsjoko 1.1 }
438     else if(!$fp) {
439     PEAR::raiseError("Connection to RPC server ".$this->server." failed");
440 joko 1.4 $this->errstr="Connect error";
441     return 0;
442 cvsjoko 1.1 }
443 cvsjoko 1.2
444 cvsjoko 1.1 // Only create the payload if it was not created previously
445     if(empty($msg->payload)) $msg->createPayload();
446 cvsjoko 1.2
447 cvsjoko 1.1 // thanks to Grant Rauscher <grant7@firstworld.net>
448     // for this
449     $credentials="";
450     if ($username!="") {
451     $credentials="Authorization: Basic " .
452     base64_encode($username . ":" . $password) . "\r\n";
453     }
454 cvsjoko 1.2
455    
456 cvsjoko 1.1 if($this->proxy) {
457     $op = "POST http://" . $this->server;
458 cvsjoko 1.2
459 cvsjoko 1.1 if($this->proxy_port) {
460     $op .= ":" . $this->port;
461     }
462     }
463     else {
464     $op = "POST ";
465     }
466 cvsjoko 1.2
467 cvsjoko 1.1 $op .= $this->path. " HTTP/1.0\r\nUser-Agent: PHP XMLRPC 1.0\r\n" .
468 cvsjoko 1.2 "Host: ". $this->server . "\r\n";
469     if ($this->proxy && $this->proxy_user != '') {
470     $op .= 'Proxy-Authorization: Basic ' .
471     base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
472     "\r\n";
473     }
474     $op .= $credentials .
475 cvsjoko 1.1 "Content-Type: text/xml\r\nContent-Length: " .
476     strlen($msg->payload) . "\r\n\r\n" .
477     $msg->payload;
478 cvsjoko 1.2
479 cvsjoko 1.1 // print($op);
480 cvsjoko 1.2
481 joko 1.4 if (!fputs($fp, $op, strlen($op))) {
482 cvsjoko 1.1 $this->errstr="Write error";
483     return 0;
484     }
485     $resp=$msg->parseResponseFile($fp);
486     fclose($fp);
487     return $resp;
488     }
489     }
490    
491    
492     class XML_RPC_Response
493     {
494     var $xv;
495     var $fn;
496     var $fs;
497     var $hdrs;
498    
499     function XML_RPC_Response($val, $fcode=0, $fstr="")
500     {
501     if ($fcode!=0) {
502     $this->fn=$fcode;
503     $this->fs=htmlspecialchars($fstr);
504     } else {
505     $this->xv=$val;
506     }
507     }
508    
509 cvsjoko 1.2 function faultCode()
510     {
511     if (isset($this->fn))
512 cvsjoko 1.1 return $this->fn;
513     else
514     return 0;
515     }
516    
517     function faultString() { return $this->fs; }
518     function value() { return $this->xv; }
519    
520 cvsjoko 1.2 function serialize() {
521 cvsjoko 1.1 $rs="<methodResponse>\n";
522     if ($this->fn) {
523     $rs.="<fault>
524     <value>
525     <struct>
526     <member>
527     <name>faultCode</name>
528     <value><int>" . $this->fn . "</int></value>
529     </member>
530     <member>
531     <name>faultString</name>
532     <value><string>" . $this->fs . "</string></value>
533     </member>
534     </struct>
535     </value>
536     </fault>";
537     } else {
538 cvsjoko 1.2 $rs.="<params>\n<param>\n" . $this->xv->serialize() .
539 cvsjoko 1.1 "</param>\n</params>";
540     }
541     $rs.="\n</methodResponse>";
542     return $rs;
543     }
544     }
545    
546    
547     class XML_RPC_Message
548     {
549     var $payload;
550     var $methodname;
551     var $params = array();
552     var $debug=0;
553    
554     function XML_RPC_Message($meth, $pars=0)
555     {
556     $this->methodname=$meth;
557     if (is_array($pars) && sizeof($pars)>0) {
558 cvsjoko 1.2 for($i=0; $i<sizeof($pars); $i++)
559 cvsjoko 1.1 $this->addParam($pars[$i]);
560     }
561     }
562    
563     function xml_header()
564     {
565     return "<?xml version=\"1.0\"?>\n<methodCall>\n";
566     }
567 cvsjoko 1.2
568 cvsjoko 1.1 function xml_footer()
569     {
570     return "</methodCall>\n";
571     }
572    
573     function createPayload()
574     {
575     $this->payload=$this->xml_header();
576     $this->payload.="<methodName>" . $this->methodname . "</methodName>\n";
577     // if (sizeof($this->params)) {
578     $this->payload.="<params>\n";
579     for($i=0; $i<sizeof($this->params); $i++) {
580     $p=$this->params[$i];
581     $this->payload.="<param>\n" . $p->serialize() .
582     "</param>\n";
583     }
584     $this->payload.="</params>\n";
585     // }
586     $this->payload.=$this->xml_footer();
587     $this->payload=str_replace("\n", "\r\n", $this->payload);
588     }
589    
590     function method($meth="")
591     {
592     if ($meth!="") {
593     $this->methodname=$meth;
594     }
595     return $this->methodname;
596     }
597    
598     function serialize()
599     {
600     $this->createPayload();
601     return $this->payload;
602     }
603    
604     function addParam($par) { $this->params[]=$par; }
605     function getParam($i) { return $this->params[$i]; }
606     function getNumParams() { return sizeof($this->params); }
607    
608     function parseResponseFile($fp)
609     {
610     $ipd="";
611    
612     while($data=fread($fp, 32768)) {
613     $ipd.=$data;
614     }
615     return $this->parseResponse($ipd);
616     }
617    
618     function parseResponse($data="")
619     {
620     global $XML_RPC_xh,$XML_RPC_err,$XML_RPC_str;
621     global $XML_RPC_defencoding;
622 cvsjoko 1.2
623 cvsjoko 1.1 $parser = xml_parser_create($XML_RPC_defencoding);
624    
625     $XML_RPC_xh[$parser]=array();
626    
627 cvsjoko 1.2 $XML_RPC_xh[$parser]['st']="";
628     $XML_RPC_xh[$parser]['cm']=0;
629     $XML_RPC_xh[$parser]['isf']=0;
630 cvsjoko 1.1 $XML_RPC_xh[$parser]['ac']="";
631     $XML_RPC_xh[$parser]['qt']="";
632 cvsjoko 1.2
633 cvsjoko 1.1 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
634     xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee");
635     xml_set_character_data_handler($parser, "XML_RPC_cd");
636     xml_set_default_handler($parser, "XML_RPC_dh");
637     $xmlrpc_value = new XML_RPC_Value;
638    
639     $hdrfnd=0;
640 cvsjoko 1.2 if ($this->debug) {
641     print "<PRE>---GOT---\n";
642     print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
643     print "\n---END---\n</PRE>";
644     }
645 cvsjoko 1.1 // see if we got an HTTP 200 OK, else bomb
646     // but only do this if we're using the HTTP protocol.
647 cvsjoko 1.2 if (ereg("^HTTP",$data) &&
648 cvsjoko 1.1 !ereg("^HTTP/[0-9\.]+ 200 ", $data)) {
649     $errstr= substr($data, 0, strpos($data, "\n")-1);
650     error_log("HTTP error, got response: " .$errstr);
651     $r=new XML_RPC_Response(0, $XML_RPC_err["http_error"],
652     $XML_RPC_str["http_error"]. " (" .
653     $errstr . ")");
654     xml_parser_free($parser);
655     return $r;
656     }
657     // gotta get rid of headers here
658 cvsjoko 1.2
659    
660     if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
661     $XML_RPC_xh[$parser]['ha'] = substr($data,0,$brpos);
662     $data= substr($data,$brpos+4);
663 cvsjoko 1.1 $hdrfnd=1;
664     }
665 cvsjoko 1.2
666 cvsjoko 1.1 if (!xml_parse($parser, $data, sizeof($data))) {
667     // thanks to Peter Kocks <peter.kocks@baygate.com>
668 cvsjoko 1.2 if((xml_get_current_line_number($parser)) == 1)
669 cvsjoko 1.1 $errstr = "XML error at line 1, check URL";
670     else
671     $errstr = sprintf("XML error: %s at line %d",
672     xml_error_string(xml_get_error_code($parser)),
673     xml_get_current_line_number($parser));
674     error_log($errstr);
675     $r=new XML_RPC_Response(0, $XML_RPC_err["invalid_return"],
676     $XML_RPC_str["invalid_return"]);
677     xml_parser_free($parser);
678     return $r;
679     }
680     xml_parser_free($parser);
681     if ($this->debug) {
682 cvsjoko 1.2 print "<PRE>---EVALING---[" .
683     strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
684 cvsjoko 1.1 htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
685     }
686     if (strlen($XML_RPC_xh[$parser]['st'])==0) {
687     // then something odd has happened
688     // and it's time to generate a client side error
689     // indicating something odd went on
690     $r=new XML_RPC_Response(0, $XML_RPC_err["invalid_return"],
691     $XML_RPC_str["invalid_return"]);
692     } else {
693     eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
694     if ($XML_RPC_xh[$parser]['isf']) {
695     $f=$v->structmem("faultCode");
696     $fs=$v->structmem("faultString");
697 cvsjoko 1.2 $r=new XML_RPC_Response($v, $f->scalarval(),
698 cvsjoko 1.1 $fs->scalarval());
699     } else {
700     $r=new XML_RPC_Response($v);
701     }
702     }
703     $r->hdrs=split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
704     return $r;
705     }
706    
707     }
708    
709    
710     class XML_RPC_Value
711     {
712     var $me=array();
713     var $mytype=0;
714    
715     function XML_RPC_Value($val=-1, $type="")
716     {
717     global $XML_RPC_Types;
718     $this->me=array();
719     $this->mytype=0;
720     if ($val!=-1 || $type!="") {
721     if ($type=="") $type="string";
722     if ($XML_RPC_Types[$type]==1) {
723     $this->addScalar($val,$type);
724     }
725     else if ($XML_RPC_Types[$type]==2)
726     $this->addArray($val);
727     else if ($XML_RPC_Types[$type]==3)
728     $this->addStruct($val);
729     }
730     }
731    
732     function addScalar($val, $type="string")
733     {
734     global $XML_RPC_Types, $XML_RPC_Boolean;
735 cvsjoko 1.2
736 cvsjoko 1.1 if ($this->mytype==1) {
737     echo "<B>XML_RPC_Value</B>: scalar can have only one value<BR>";
738     return 0;
739     }
740     $typeof=$XML_RPC_Types[$type];
741     if ($typeof!=1) {
742     echo "<B>XML_RPC_Value</B>: not a scalar type (${typeof})<BR>";
743     return 0;
744     }
745 cvsjoko 1.2
746 cvsjoko 1.1 if ($type==$XML_RPC_Boolean) {
747 cvsjoko 1.2 if (strcasecmp($val,"true")==0 ||
748     $val==1 ||
749     ($val==true &&
750 cvsjoko 1.1 strcasecmp($val,"false"))) {
751 cvsjoko 1.2
752 cvsjoko 1.1 $val=1;
753     } else {
754     $val=0;
755     }
756     }
757 cvsjoko 1.2
758 cvsjoko 1.1 if ($this->mytype==2) {
759     // we're adding to an array here
760     $ar=$this->me["array"];
761     $ar[]=new XML_RPC_Value($val, $type);
762     $this->me["array"]=$ar;
763     } else {
764     // a scalar, so set the value and remember we're scalar
765     $this->me[$type]=$val;
766     $this->mytype=$typeof;
767     }
768     return 1;
769     }
770    
771     function addArray($vals)
772     {
773     global $XML_RPC_Types;
774     if ($this->mytype!=0) {
775 cvsjoko 1.2 echo "<B>XML_RPC_Value</B>: already initialized as a [" .
776 cvsjoko 1.1 $this->kindOf() . "]<BR>";
777     return 0;
778     }
779     $this->mytype=$XML_RPC_Types["array"];
780     $this->me["array"]=$vals;
781     return 1;
782     }
783    
784     function addStruct($vals)
785     {
786     global $XML_RPC_Types;
787     if ($this->mytype!=0) {
788 cvsjoko 1.2 echo "<B>XML_RPC_Value</B>: already initialized as a [" .
789 cvsjoko 1.1 $this->kindOf() . "]<BR>";
790     return 0;
791     }
792     $this->mytype=$XML_RPC_Types["struct"];
793     $this->me["struct"]=$vals;
794     return 1;
795     }
796    
797     function dump($ar)
798     {
799     reset($ar);
800     while ( list( $key, $val ) = each( $ar ) ) {
801     echo "$key => $val<br>";
802     if ($key == 'array')
803     while ( list( $key2, $val2 ) = each( $val ) ) {
804     echo "-- $key2 => $val2<br>";
805     }
806     }
807     }
808    
809     function kindOf()
810     {
811     switch($this->mytype) {
812     case 3:
813     return "struct";
814     break;
815     case 2:
816     return "array";
817     break;
818     case 1:
819     return "scalar";
820     break;
821     default:
822     return "undef";
823     }
824     }
825    
826     function serializedata($typ, $val)
827     {
828     $rs="";
829     global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
830     switch($XML_RPC_Types[$typ]) {
831     case 3:
832     // struct
833     $rs.="<struct>\n";
834     reset($val);
835     while(list($key2, $val2)=each($val)) {
836     $rs.="<member><name>${key2}</name>\n";
837     $rs.=$this->serializeval($val2);
838     $rs.="</member>\n";
839     }
840     $rs.="</struct>";
841     break;
842     case 2:
843     // array
844     $rs.="<array>\n<data>\n";
845     for($i=0; $i<sizeof($val); $i++) {
846     $rs.=$this->serializeval($val[$i]);
847     }
848     $rs.="</data>\n</array>";
849     break;
850     case 1:
851     switch ($typ) {
852     case $XML_RPC_Base64:
853     $rs.="<${typ}>" . base64_encode($val) . "</${typ}>";
854     break;
855     case $XML_RPC_Boolean:
856     $rs.="<${typ}>" . ($val ? "1" : "0") . "</${typ}>";
857     break;
858     case $XML_RPC_String:
859     $rs.="<${typ}>" . htmlspecialchars($val). "</${typ}>";
860     break;
861     default:
862     $rs.="<${typ}>${val}</${typ}>";
863     }
864     break;
865     default:
866     break;
867     }
868     return $rs;
869     }
870    
871     function serialize()
872     {
873     return $this->serializeval($this);
874     }
875    
876     function serializeval($o)
877     {
878     global $XML_RPC_Types;
879     $rs="";
880     $ar=$o->me;
881     reset($ar);
882     list($typ, $val) = each($ar);
883     $rs.="<value>";
884     $rs.=$this->serializedata($typ, $val);
885     $rs.="</value>\n";
886     return $rs;
887     }
888    
889     function structmem($m)
890     {
891     $nv=$this->me["struct"][$m];
892     return $nv;
893     }
894    
895     function structreset()
896     {
897     reset($this->me["struct"]);
898     }
899 cvsjoko 1.2
900 cvsjoko 1.1 function structeach()
901     {
902     return each($this->me["struct"]);
903     }
904 cvsjoko 1.2
905 cvsjoko 1.1 function getval() {
906     // UNSTABLE
907     global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
908 cvsjoko 1.2
909 cvsjoko 1.1 reset($this->me);
910     list($a,$b)=each($this->me);
911 cvsjoko 1.2
912 cvsjoko 1.1 // contributed by I Sofer, 2001-03-24
913     // add support for nested arrays to scalarval
914     // i've created a new method here, so as to
915     // preserve back compatibility
916    
917     if (is_array($b)) {
918     foreach ($b as $id => $cont) {
919     $b[$id] = $cont->scalarval();
920     }
921     }
922    
923     // add support for structures directly encoding php objects
924     if (is_object($b)) {
925     $t = get_object_vars($b);
926     foreach ($t as $id => $cont) {
927     $t[$id] = $cont->scalarval();
928     }
929     foreach ($t as $id => $cont) {
930     eval('$b->'.$id.' = $cont;');
931     }
932     }
933 cvsjoko 1.2
934 cvsjoko 1.1 // end contrib
935     return $b;
936     }
937 cvsjoko 1.2
938 cvsjoko 1.1 function scalarval()
939     {
940     global $XML_RPC_Boolean, $XML_RPC_Base64;
941     reset($this->me);
942     list($a,$b)=each($this->me);
943     return $b;
944     }
945    
946     function scalartyp()
947     {
948     global $XML_RPC_I4, $XML_RPC_Int;
949     reset($this->me);
950     list($a,$b)=each($this->me);
951 cvsjoko 1.2 if ($a==$XML_RPC_I4)
952 cvsjoko 1.1 $a=$XML_RPC_Int;
953     return $a;
954     }
955    
956     function arraymem($m)
957     {
958     $nv=$this->me["array"][$m];
959     return $nv;
960     }
961    
962     function arraysize()
963     {
964     reset($this->me);
965     list($a,$b)=each($this->me);
966     return sizeof($b);
967     }
968     }
969    
970    
971     /**
972     * date helpers
973     */
974     function XML_RPC_iso8601_encode($timet, $utc=0) {
975     // return an ISO8601 encoded string
976     // really, timezones ought to be supported
977     // but the XML-RPC spec says:
978     //
979     // "Don't assume a timezone. It should be specified by the server in its
980     // documentation what assumptions it makes about timezones."
981 cvsjoko 1.2 //
982     // these routines always assume localtime unless
983 cvsjoko 1.1 // $utc is set to 1, in which case UTC is assumed
984     // and an adjustment for locale is made when encoding
985     if (!$utc) {
986     $t=strftime("%Y%m%dT%H:%M:%S", $timet);
987     } else {
988 cvsjoko 1.2 if (function_exists("gmstrftime"))
989 cvsjoko 1.1 // gmstrftime doesn't exist in some versions
990     // of PHP
991     $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet);
992     else {
993     $t=strftime("%Y%m%dT%H:%M:%S", $timet-date("Z"));
994     }
995     }
996 cvsjoko 1.2
997 cvsjoko 1.1 return $t;
998     }
999    
1000     function XML_RPC_iso8601_decode($idate, $utc=0) {
1001     // return a timet in the localtime, or UTC
1002     $t=0;
1003     if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})",$idate, $regs)) {
1004 cvsjoko 1.2
1005 cvsjoko 1.1 if ($utc) {
1006     $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1007     } else {
1008     $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
1009     }
1010 cvsjoko 1.2 }
1011 cvsjoko 1.1
1012     return $t;
1013     }
1014    
1015     /******************************************************************
1016     * XML_RPC_decode takes a message in PHP XML_RPC object format and *
1017     * tranlates it into native PHP types. *
1018     * *
1019     * author: Dan Libby (dan@libby.com) *
1020     ******************************************************************/
1021     function XML_RPC_decode($XML_RPC_val) {
1022     $kind = $XML_RPC_val->kindOf();
1023    
1024     if($kind == "scalar") {
1025     return $XML_RPC_val->scalarval();
1026     }
1027     else if($kind == "array") {
1028     $size = $XML_RPC_val->arraysize();
1029     $arr = array();
1030    
1031     for($i = 0; $i < $size; $i++) {
1032     $arr[]=XML_RPC_decode($XML_RPC_val->arraymem($i));
1033     }
1034 cvsjoko 1.2 return $arr;
1035 cvsjoko 1.1 }
1036     else if($kind == "struct") {
1037     $XML_RPC_val->structreset();
1038     $arr = array();
1039    
1040     while(list($key,$value)=$XML_RPC_val->structeach()) {
1041     $arr[$key] = XML_RPC_decode($value);
1042     }
1043     return $arr;
1044     }
1045     }
1046    
1047     /*****************************************************************
1048     * XML_RPC_encode takes native php types and encodes them into *
1049     * XML_RPC PHP object format. *
1050     * BUG: All sequential arrays are turned into structs. I don't *
1051     * know of a good way to determine if an array is sequential *
1052     * only. *
1053     * *
1054     * feature creep -- could support more types via optional type *
1055     * argument. *
1056     * *
1057     * author: Dan Libby (dan@libby.com) *
1058     *****************************************************************/
1059     function XML_RPC_encode($php_val) {
1060     global $XML_RPC_Boolean;
1061     global $XML_RPC_Int;
1062     global $XML_RPC_Double;
1063     global $XML_RPC_String;
1064     global $XML_RPC_Array;
1065     global $XML_RPC_Struct;
1066    
1067     $type = gettype($php_val);
1068     $XML_RPC_val = new XML_RPC_value;
1069    
1070     switch($type) {
1071     case "array":
1072     case "object":
1073     $arr = array();
1074     while (list($k,$v) = each($php_val)) {
1075     $arr[$k] = XML_RPC_encode($v);
1076     }
1077     $XML_RPC_val->addStruct($arr);
1078     break;
1079     case "integer":
1080     $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
1081     break;
1082     case "double":
1083     $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
1084     break;
1085     case "string":
1086     case "NULL":
1087     $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
1088     break;
1089     // <G_Giunta_2001-02-29>
1090     // Add support for encoding/decoding of booleans, since they are supported in PHP
1091     case "boolean":
1092     $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
1093     break;
1094     // </G_Giunta_2001-02-29>
1095     case "unknown type":
1096     default:
1097     $XML_RPC_val = false;
1098     break;
1099     }
1100     return $XML_RPC_val;
1101     }
1102    
1103     ?>

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