]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/XMLRPC/xmlrpc_emu.inc
RdfWriter: use UriResolver
[SourceForge/phpwiki.git] / lib / XMLRPC / xmlrpc_emu.inc
1 <?php
2
3 /*
4 xmlrpc_emu.inc -- xmlrpc.inc wrapper.
5
6 08/30/01 - last modified by Dan Libby <dan@libby.com>
7
8 This code provides API compatibility with Edd Dumbill's php xmlrpc
9 library (http://phpxmlrpc.sourceforge.net/) but uses the xmlrpc-epi 
10 engine for the actual xml processing.  It is intended to provide a 
11 smooth transition path for those who would like to be able to use either
12 implementation.
13
14 To use in your existing application, simply change:
15
16 include("xmlrpc.inc");
17
18 to:
19
20 include("xmlrpc_emu.inc");
21
22 Notes:
23 - This file requires that xmlrpc-epi C extension be installed.
24   See http://xmlrpc-epi.sourceforge.net/
25
26 - xmlrpc_decode, xmlrpc_encode are present in both the xmlrpc-epi
27   C extension and the usefulinc implementation, and conflict.
28   They have been enhanced and renamed to val_to_php, php_to_val.
29
30 - Certain methods are not implemented and will typically return
31   a message saying so.
32
33 */
34
35 // by Edd Dumbill (C) 1999-2001
36 // <edd@usefulinc.com>
37 //
38
39 // $Id: xmlrpc_emu.inc,v 1.2 2007-01-21 23:28:51 rurban Exp $
40
41
42 // Copyright (c) 1999,2000,2001 Edd Dumbill.
43 // All rights reserved.
44 //
45 // Redistribution and use in source and binary forms, with or without
46 // modification, are permitted provided that the following conditions
47 // are met:
48 //
49 //    * Redistributions of source code must retain the above copyright
50 //      notice, this list of conditions and the following disclaimer.
51 //
52 //    * Redistributions in binary form must reproduce the above
53 //      copyright notice, this list of conditions and the following
54 //      disclaimer in the documentation and/or other materials provided
55 //      with the distribution.
56 //
57 //    * Neither the name of the "PHP for XML-RPC" nor the names of its
58 //      contributors may be used to endorse or promote products derived
59 //      from this software without specific prior written permission.
60 //
61 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
62 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
64 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
65 // REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
66 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
67 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
68 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
70 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
72 // OF THE POSSIBILITY OF SUCH DAMAGE.
73
74 // Requires: transport.php
75
76 // change path as necessary. or set before including this file.
77 if(!$xmlrpc_util_path) {
78    $xmlrpc_util_path = "./utils/";
79 }
80 include_once("$xmlrpc_util_path/utils.php");
81
82 // xmlrpc types.  seems like these should be defines instead of globals.
83 $xmlrpcI4="i4";
84 $xmlrpcInt="int";
85 $xmlrpcBoolean="boolean";
86 $xmlrpcDouble="double";
87 $xmlrpcString="string";
88 $xmlrpcDateTime="dateTime.iso8601";
89 $xmlrpcBase64="base64";
90 $xmlrpcArray="array";
91 $xmlrpcStruct="struct";
92
93 // map local types to xmlrpc-epi-php types.
94 $epiTypeMap = array($xmlrpcI4 => "int",
95                     $xmlrpcInt => "int",
96                     $xmlrpcBoolean => "boolean",
97                     $xmlrpcString => "string",
98                     $xmlrpcDouble => "double",
99                     $xmlrpcDateTime => "datetime",
100                     $xmlrpcBase64 => "base64",
101                     $xmlrpcArray => "array",
102                     $xmlrpcStruct => "struct");
103
104 // map local types to php types
105 $phpTypeMap = array($xmlrpcI4 => "integer",
106                     $xmlrpcInt => "integer",
107                     $xmlrpcBoolean => "boolean",
108                     $xmlrpcString => "string",
109                     $xmlrpcDouble => "double",
110                     $xmlrpcDateTime => "string",
111                     $xmlrpcBase64 => "string",
112                     $xmlrpcArray => "array",
113                     $xmlrpcStruct => "array");
114
115 $xmlrpcTypes=array($xmlrpcI4 => 1,
116                    $xmlrpcInt => 1,
117                    $xmlrpcBoolean => 1,
118                    $xmlrpcString => 1,
119                    $xmlrpcDouble => 1,
120                    $xmlrpcDateTime => 1,
121                    $xmlrpcBase64 => 1,
122                    $xmlrpcArray => 2,
123                    $xmlrpcStruct => 3);
124
125 // some error definitions
126 $xmlrpcerr["unknown_method"]=1;
127 $xmlrpcstr["unknown_method"]="Unknown method";
128 $xmlrpcerr["invalid_return"]=2;
129 $xmlrpcstr["invalid_return"]="Invalid return payload: enabling debugging to examine incoming payload";
130 $xmlrpcerr["incorrect_params"]=3;
131 $xmlrpcstr["incorrect_params"]="Incorrect parameters passed to method";
132 $xmlrpcerr["introspect_unknown"]=4;
133 $xmlrpcstr["introspect_unknown"]="Can't introspect: method unknown";
134 $xmlrpcerr["http_error"]=5;
135 $xmlrpcstr["http_error"]="Didn't receive 200 OK from remote server.";
136 $xmlrpcerr["no_data"]=6;
137 $xmlrpcstr["no_data"]="No data received from server.";
138 $xmlrpcerr["no_ssl"]=7;
139 $xmlrpcstr["no_ssl"]="No SSL support compiled in.";
140 $xmlrpcerr["curl_fail"]=8;
141 $xmlrpcstr["curl_fail"]="CURL error";
142
143 $xmlrpc_defencoding="UTF-8";
144
145 $xmlrpcName="XML-RPC for PHP (xmlrpc-epi wrapper version)";
146 $xmlrpcVersion="1.0";
147
148 // let user errors start at 800
149 $xmlrpcerruser=800; 
150
151
152 /************************************************
153 * xmlrpc client class.  basically a wrapper for *
154 * xu_rpc_http().                                *
155 ************************************************/
156 class xmlrpc_client {
157    var $path;
158    var $server;
159    var $port;
160    var $errno;
161    var $errstring;
162    var $debug=0;
163    var $username="";
164    var $password="";
165
166    // constructor
167    function xmlrpc_client($path, $server, $port=80) {
168       $this->port=$port; $this->server=$server; $this->path=$path;
169    }
170
171    // public. for debugging info.
172    function setDebug($in) {
173       if ($in) {
174          $this->debug=1;
175       } else {
176          $this->debug=0;
177       }
178    }
179
180    // public. for http authentication.
181    function setCredentials($u, $p) {
182       $this->username=$u;
183       $this->password=$p;
184    }
185
186    // public.  sent request to server.
187    function send($msg, $timeout=0, $pause=0, $secure=false) {
188       // where msg is an xmlrpcmsg
189       $msg->debug=$this->debug;
190
191
192       if ($pause) {
193          sleep($pause);
194       }
195
196       return $this->sendPayloadHTTP10($msg, $this->server, $this->port, $timeout, $this->username, $this->password);
197
198    }
199
200    // private. performs http post request
201    function sendPayloadHTTP10($msg, $server, $port, $timeout=0, $username="", $password="", $secure=false) {
202       // Only create the payload if it was not created previously
203       if (empty($msg->payload)) {
204          $msg->createPayload();
205       }
206
207       $response_buf = xu_query_http_post($msg->payload, $server, $this->path, $port, 
208                                          $this->debug, $timeout, $username, $password, $secure);
209
210       $resp=$msg->parseResponse($response_buf);
211
212       return $resp;
213    }
214
215 } // end class xmlrpc_client
216
217 /******************************************
218 * a class to represent an xmlrpc response *
219 ******************************************/
220 class xmlrpcresp {
221    var $xv;
222    var $fn;
223    var $fs;
224    var $hdrs;
225
226    // constructor.
227    function xmlrpcresp($val, $fcode=0, $fstr="") {
228       if ($fcode!=0) {
229          $this->fn=$fcode;
230          $this->fs=$fstr;
231       } else {
232          $this->xv=$val;
233       }
234    }
235
236    // public. get methods
237    function faultCode() { return $this->fn;}
238    function faultString() { return $this->fs;}
239    function value() { return $this->xv;}
240
241    // public. serialize self as xml string.
242    function serialize() {
243       /* check if fault */
244       if ($this->fn) {
245          $result = xmlrpc_encode_request(null, xu_fault_code($this->fn, $this->fs));
246       } else {
247          $php_vals = val_to_php($this->xv);
248
249          // null for methodname indicates response type.
250          $result = xmlrpc_encode_request(null, $php_vals);
251       }
252
253       return $result;
254    }
255 }
256
257 /*****************************************
258 * a class to represent an xmlrpc message *
259 *****************************************/
260 class xmlrpcmsg {
261    var $payload;
262    var $methodname;
263    var $params=array();
264    var $debug=0;
265
266    // constructor
267    function xmlrpcmsg($meth, $pars=0) {
268       $this->methodname=$meth;
269       if (is_array($pars) && sizeof($pars)>0) {
270          for ($i=0; $i<sizeof($pars); $i++)
271             $this->addParam($pars[$i]);
272       }
273    }
274
275    // unused. xmlrpc-epi does this automagically
276    function xml_header() {
277       return "xml_header not supported";
278    }
279
280    // unused. not necessary
281    function xml_footer() {
282       return "xml_footer not supported";
283    }
284
285    // private. performs the actual message serialization.
286    function createPayload() {
287       $php_params_val = array();
288       foreach($this->params as $param) {
289          $php_params_val[] = val_to_php($param);
290       }
291       $this->payload = xmlrpc_encode_request($this->methodname, $php_params_val);
292    }
293
294    // public. returns name of method
295    function method($meth="") {
296       if ($meth!="") {
297          $this->methodname=$meth;
298       }
299       return $this->methodname;
300    }
301
302    // public. serialization message as xml
303    function serialize() {
304       $this->createPayload();
305       return $this->payload;
306    }
307
308    // public. add/retrieve/count message params
309    function addParam($par) { $this->params[]=$par;}
310    function getParam($i) { return $this->params[$i];}
311    function getNumParams() { return sizeof($this->params);}
312
313    // public. in case we are given a file handle
314    function parseResponseFile($fp) {
315       $ipd="";
316
317       while ($data=fread($fp, 32768)) {
318          $ipd.=$data;
319       }
320       return $this->parseResponse($ipd);
321    }
322
323    // public. parse xml, return as xmlrpcresp.
324    function parseResponse($data="") {
325       $php_val = xmlrpc_decode($data);
326
327       /* check for fault */
328       if (is_array($php_val) && isset($php_val[0][faultCode])) {
329          $fc = $php_val[0][faultCode];
330          $fs = $php_val[0][faultString];
331       } else {
332          $rpc_val = php_to_val($php_val);
333       }
334
335
336       return new xmlrpcresp($rpc_val, $fc, $fs);
337    }
338
339 }
340
341 /***************************************
342 * a class to represent an xmlrpc value *
343 ***************************************/
344 class xmlrpcval {
345    var $me=array();
346    var $mytype=0;
347
348    // constructor
349    function xmlrpcval($val=-1, $type="") {
350       global $xmlrpcTypes;
351       $this->me=array();
352       $this->mytype=0;
353       if ($val!=-1 || $type!="") {
354          if ($type=="") $type="string";
355          if ($xmlrpcTypes[$type]==1) {
356             $this->addScalar($val,$type);
357          } else if ($xmlrpcTypes[$type]==2)
358             $this->addArray($val);
359          else if ($xmlrpcTypes[$type]==3)
360             $this->addStruct($val);
361       }
362    }
363
364    // public. add a php scalar value.
365    function addScalar($val, $type="string") {
366       global $xmlrpcTypes, $xmlrpcBoolean;
367
368       if ($this->mytype==1) {
369          echo "<B>xmlrpcval</B>: scalar can have only one value<BR>";
370          return 0;
371       }
372       $typeof=$xmlrpcTypes[$type];
373       if ($typeof!=1) {
374          echo "<B>xmlrpcval</B>: not a scalar type (${typeof})<BR>";
375          return 0;
376       }
377
378       if ($type==$xmlrpcBoolean) {
379          if (strcasecmp($val,"true")==0 || $val==1 || $val==true) {
380             $val=1;
381          } else {
382             $val=0;
383          }
384       }
385
386       if ($this->mytype==2) {
387          // we're adding to an array here
388          $ar=$this->me["array"];
389          $ar[]=new xmlrpcval($val, $type);
390          $this->me["array"]=$ar;
391       } else {
392          // a scalar, so set the value and remember we're scalar
393          $this->me[$type]=$val;
394          $this->mytype=$typeof;
395       }
396       return 1;
397    }
398
399    // public. add a php array
400    function addArray($vals) {
401       global $xmlrpcTypes;
402       if ($this->mytype!=0) {
403          echo "<B>xmlrpcval</B>: already initialized as a [" . 
404          $this->kindOf() . "]<BR>";
405          return 0;
406       }
407       $this->mytype=$xmlrpcTypes["array"];
408       $this->me["array"]=$vals;
409       return 1;
410    }
411
412    // public. add a php keyed array as a struct.
413    function addStruct($vals) {
414       global $xmlrpcTypes;
415       if ($this->mytype!=0) {
416          echo "<B>xmlrpcval</B>: already initialized as a [" . 
417          $this->kindOf() . "]<BR>";
418          return 0;
419       }
420       $this->mytype=$xmlrpcTypes["struct"];
421       $this->me["struct"]=$vals;
422       return 1;
423    }
424
425    // public. write myself out as html.
426    function dump($ar) {
427       foreach($ar as $key => $val) {
428          echo "$key => $val<br>";
429          if ($key == 'array') {
430             foreach($val as $key2 => $val2) {
431                echo "-- $key2 => $val2";
432             }
433          }
434       }
435    }
436
437    // public. kind of value. 
438    // (not 1 to 1 mapping with xmlrpc types or php types)
439    function kindOf() {
440       switch ($this->mytype) {
441       case 3:
442          return "struct";
443          break;
444       case 2:
445          return "array";
446          break;
447       case 1:
448          return "scalar";
449          break;
450       default:
451          return "undef";
452       }
453    }
454
455    // unused.
456    function serializedata($typ, $val) {
457       return "serializedata not supported";
458    }
459
460    // public. serialize self as xml.
461    function serialize() {
462       return $this->serializeval($this);
463    }
464
465    // public. serialize any xmlrpcval object as xml.
466    function serializeval($o) {
467       $php_val = val_to_php($o);
468       $result_xml = xmlrpc_encode($php_val);
469
470       return $result_xml;
471    }
472
473    // public.  get struct members.
474    function structmem($m) {
475       $nv=$this->me["struct"][$m];
476       return $nv;
477    }
478
479    // public. reset struct to first item.
480    function structreset() {
481       reset($this->me["struct"]);
482    }
483
484    // public. get key/val pair of next struct item.
485    function structeach() {
486       return each($this->me["struct"]);
487    }
488
489    // public. get php type scalar value.
490    function scalarval() {
491       global $xmlrpcBoolean, $xmlrpcBase64;
492       reset($this->me);
493       list($a,$b)=each($this->me);
494       return $b;
495    }
496
497    // public. get xmlrpc type of value.
498    function scalartyp() {
499       global $xmlrpcI4, $xmlrpcInt;
500       reset($this->me);
501       list($a,$b)=each($this->me);
502       if ($a==$xmlrpcI4)
503          $a=$xmlrpcInt;
504       return $a;
505    }
506
507    // public. get array member.
508    function arraymem($m) {
509       $nv=$this->me["array"][$m];
510       return $nv;
511    }
512
513    // public. get array size
514    function arraysize() {
515       reset($this->me);
516       list($a,$b)=each($this->me);
517       return sizeof($b);
518    }
519 }
520
521 // date helpers
522
523 /*****************************************************************
524 * These stubs need to be implemented in the C extension library. *
525 * When they are, these calls will be commented out. -danda       *
526 *****************************************************************/
527
528 function iso8601_encode($timet, $utc=0) {
529    // return an ISO8601 encoded string
530    // really, timezones ought to be supported
531    // but the XML-RPC spec says:
532    //
533    // "Don't assume a timezone. It should be specified by the server in its
534    // documentation what assumptions it makes about timezones."
535    // 
536    // these routines always assume localtime unless 
537    // $utc is set to 1, in which case UTC is assumed
538    // and an adjustment for locale is made when encoding
539    if (!$utc) {
540       $t=strftime("%Y%m%dT%H:%M:%S", $timet);
541    } else {
542       if (function_exists("gmstrftime"))
543          // gmstrftime doesn't exist in some versions
544          // of PHP
545          $t=gmstrftime("%Y%m%dT%H:%M:%S", $timet);
546       else {
547          $t=strftime("%Y%m%dT%H:%M:%S", $timet-date("Z"));
548       }
549    }
550    return $t;
551 }
552
553 function iso8601_decode($idate, $utc=0) {
554    // return a timet in the localtime, or UTC
555    $t=0;
556    if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})",
557             $idate, $regs)) {
558       if ($utc) {
559          $t=gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
560       } else {
561          $t=mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
562       }
563    }
564    return $t;
565 }
566
567 /****************************************************************
568 * xmlrpc_decode takes a message in PHP xmlrpc object format and *
569 * tranlates it into native PHP types.                           *
570 ****************************************************************/
571 function val_to_php($xmlrpc_val) {
572    global $epiTypeMap;
573    global $phpTypeMap;
574
575    $kind = $xmlrpc_val->kindOf();
576
577    if ($kind == "scalar") {
578       $type = $xmlrpc_val->scalartyp();
579       $php_val = $xmlrpc_val->scalarval();
580       $php_type = $phpTypeMap[$type];
581
582       // value is stored in object as a string. we want
583       // its native type.
584       settype($php_val, $php_type);
585
586       // magic to let xmlprc-epi engine know about base64 and datetime types.
587       $epi_type = $epiTypeMap[$type];
588       if($epi_type) {
589          xmlrpc_set_type($php_val, $epi_type);
590          // php_val may now be an object, if epi_type = base64 or datetime.
591       }
592       
593       return $php_val;
594    }
595    // generate php indexed array. recurse for sub-values.
596    else if ($kind == "array") {
597       $size = $xmlrpc_val->arraysize();
598       $arr = array();
599
600       for ($i = 0; $i < $size; $i++) {
601          $arr[] = val_to_php($xmlrpc_val->arraymem($i));
602       }
603       return $arr; 
604    } 
605    // generate php keyed array. recurse for sub-values.
606    else if ($kind == "struct") {
607       $xmlrpc_val->structreset();
608       $arr = array();
609
610       while (list($key,$value)=$xmlrpc_val->structeach()) {
611          $arr[$key] = val_to_php($value);
612       }
613       return $arr;
614    }
615 }
616
617 /****************************************************************
618 * php_to_val takes native php types and encodes them into       *
619 * xmlrpc PHP object format.                                     *
620 ****************************************************************/
621 function php_to_val($php_val) {
622    global $xmlrpcInt;
623    global $xmlrpcDouble;
624    global $xmlrpcString;
625    global $xmlrpcArray;
626    global $xmlrpcStruct;
627    global $xmlrpcBoolean;
628    global $xmlrpcDateTime;
629    global $xmlrpcBase64;
630
631    // get the xmlrpc type of value.
632    $type = xmlrpc_get_type($php_val);
633    $xmlrpc_val = new xmlrpcval;
634
635    switch ($type) {
636    case "array":
637    case "vector":         //unused
638       $arr = array();
639       foreach($php_val as $v) {
640          $arr[] = php_to_val($v);
641       }
642       $xmlrpc_val->addArray($arr);
643       break;
644    case "object":         //unused
645    case "struct":
646       foreach($php_val as $k => $v) {
647          $arr[$k] = php_to_val($v);
648       }
649       $xmlrpc_val->addStruct($arr);
650       break;
651    case "integer":        //unused
652    case "int":
653       $xmlrpc_val->addScalar($php_val, $xmlrpcInt);
654       break;
655    case "boolean":
656       $xmlrpc_val->addScalar($php_val, $xmlprcBoolean);
657       break;
658    case "double":
659       $xmlrpc_val->addScalar($php_val, $xmlrpcDouble);
660       break;
661    case "string":
662       $xmlrpc_val->addScalar($php_val, $xmlrpcString);
663       break;
664    case "datetime":
665       $xmlrpc_val->addScalar($php_val->scalar, $xmlrpcDateTime);
666       break;
667    case "base64":
668       $xmlrpc_val->addScalar($php_val->scalar, $xmlrpcBase64);
669       break;
670    case "unknown type":
671    default:
672       $xmlrpc_val = false;
673       break;
674    }
675    return $xmlrpc_val;
676 }
677
678 ?>