]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/XMLRPC/xmlrpcs_emu.inc
split is deprecated, replace with explode
[SourceForge/phpwiki.git] / lib / XMLRPC / xmlrpcs_emu.inc
1 <?php
2
3 /*
4 xmlrpcs_emu.inc -- xmlrpcs.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("xmlrpcs.inc");
17
18 to:
19
20 include("xmlrpcs_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 - the xmlrpc-epi engine uses different fault codes and strings than
31   the xmlrpc.inc. Application fault codes will remain unchanged
32   between implementations, but system codes will likely be
33   different.  
34   See http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
35
36 - Certain methods are not implemented and will typically return
37   a message saying so.
38
39 */
40
41
42 // by Edd Dumbill (C) 1999,2000
43 // <edd@usefulinc.com>
44 // $Id$
45
46 // License is granted to use or modify this software ("XML-RPC for PHP")
47 // for commercial or non-commercial use provided the copyright of the author
48 // is preserved in any distributed or derivative work.
49
50 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
51 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
53 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
54 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
56 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
57 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
58 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
59 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60
61 // XML RPC Server class
62 // requires: transport.php, xmlrpc_emu.inc
63
64 // change path as necessary. or set before including this file.
65 if(!$xmlrpc_util_path) {
66    $xmlrpc_util_path = "./utils/";
67 }
68
69 include_once("$xmlrpc_util_path/utils.php");
70 include_once("$xmlrpc_util_path/xmlrpc_emu.inc");
71
72 /*************************************************************
73 * The Introspection callback is called when an introspection *
74 * request is received by the xmlrpc server. It is a private  *
75 * function and should never be called directly.              *
76 *                                                            *
77 * It translates useful_inc style introspection data for all  *
78 * of the registered methods into xmlrpc-epi style xml, which *
79 * is then returned to the server, parsed, and possibly spit  *
80 * out as xmlrpc.                                             *
81 *************************************************************/
82 function _introspection_cb($userdata) {
83    foreach($userdata as $name => $method) {
84       if($incr++ > 0) break;
85       $sigs_buf = "";
86       $purpose = "";
87
88       if(isset($method[docstring])) {
89           $purpose = "<purpose>$method[docstring]</purpose>";
90       }
91
92       if(is_array($method[signature])) {
93          $sigs_buf = "<signatures>";
94          foreach($method[signature] as $sig) {
95             $count = 0;
96             $params = "";
97             foreach($sig as $param) {
98                $xml = "<value type='$param'/>\n";
99
100                if($count++ == 0) {
101                   $returns = $xml;
102                }
103                else {
104                   $params .= $xml;
105                }
106             }
107
108             $sigs_buf .= 
109                "<signature><params>$params</params><returns>$returns</returns></signature>\n";
110          }
111          $sigs_buf .= "</signatures>";
112       }
113
114       $method_desc .= 
115          "<methodDescription name='$name'>\n$purpose\n$sigs_buf\n</methodDescription>\n";
116    }
117
118    $xml = "<?xml version='1.0'?>\n\n<introspection version='1.0'>\n<methodList>$method_desc</methodList></introspection>\n";
119    return $xml;
120 }
121
122 /********************************************************************
123 * xmlrpc_server class.  Wrappers around the xmlrpc-epi server APIs. *
124 ********************************************************************/
125 class xmlrpc_server {
126    var $dmap = array();
127    var $xmlrpc_server;
128
129    // constructor. creates server and optionally services request.
130    function xmlrpc_server($dispMap, $serviceNow=1) {
131       global $HTTP_RAW_POST_DATA;
132       // dispMap is a despatch array of methods
133       // mapped to function names and signatures
134       // if a method
135       // doesn't appear in the map then an unknown
136       // method error is generated
137       $this->dmap = $dispMap;
138
139       // create server.
140       // php has no destructor support currently, so we can't call xmlrpc_server_destroy()
141       // at the end like we should. Fortunately, the C code takes care of this at the
142       // end of the request.  Feels unclean though.
143       $this->xmlrpc_server = xmlrpc_server_create();
144
145       // register methods
146       foreach($this->dmap as $name => $method) {
147          xmlrpc_server_register_method($this->xmlrpc_server, $name, "xmlrpc_user_func_wrapper_cb");
148       }
149
150       // register a callback in case of introspection queries.
151       xmlrpc_server_register_introspection_callback($this->xmlrpc_server, "_introspection_cb");
152
153       // possibly go to work handling request
154       if ($serviceNow) {
155          $this->service();
156       }
157    }
158
159    // private. not really useful anymore since this is all handled by the xmlrpc-epi stuff.
160    function serializeDebug() {
161       global $_xmlrpc_debuginfo;
162       if ($_xmlrpc_debuginfo!="")
163          return "<!-- DEBUG INFO:\n\n" .
164          $_xmlrpc_debuginfo . "\n-->\n";
165       else
166          return "";
167    }
168    
169    // public. service the xmlrpc request
170    function service() {
171       global $HTTP_RAW_POST_DATA;
172       $data = $HTTP_RAW_POST_DATA;
173       if (is_null($data))
174           trigger_error("empty \$HTTP_RAW_POST_DATA", E_USER_WARNING);
175
176       // call server
177       $payload = xmlrpc_server_call_method($this->xmlrpc_server, $data, $this->dmap, 
178                                            array('output_type' => "xml", 'version' => "xmlrpc"));
179       Header("Content-type: text/xml\nContent-length: " . strlen($payload));
180       echo $payload;
181    }
182
183    // private. no equivalent in C library (yet)
184    function verifySignature($in, $sig) {
185       return "verifySignature not supported";
186    }
187
188    // public. this used to be called by service(). 
189    // it's no longer necessary, but we keep it around in case 
190    // people are calling it directly from applications.
191    function parseRequest($data="") {
192       global $_xh, $HTTP_RAW_POST_DATA;
193
194       global $xmlrpcerr, $xmlrpcstr, $xmlrpcerrxml, $xmlrpc_defencoding;
195
196       if ($data == "") {
197          $data = $HTTP_RAW_POST_DATA;
198       }
199
200       // call server
201       $php_val = xmlrpc_server_call_method($this->xmlrpc_server, $data, $this->dmap, 
202                                            array('output_type' => "php", 'version' => "xmlrpc"));
203
204       /* check for fault */
205       if (is_array($php_val) && isset($php_val['faultCode'])) {
206          $fc = $php_val['faultCode'];
207          $fs = $php_val['faultString'];
208       } else {
209          $rpc_val = php_to_val($php_val);
210       }
211       $response = new xmlrpcresp($rpc_val, $fc, $fs);
212
213       return $response;
214    }
215
216    // public.  test routine.
217    function echoInput() {
218       global $HTTP_RAW_POST_DATA;
219
220       // a debugging routine: just echos back the input
221       // packet as a string value
222
223       $r = new xmlrpcresp;
224       $r->xv = new xmlrpcval( "'Aha said I: '" . $HTTP_RAW_POST_DATA, "string");
225       print $r->serialize();
226    }
227 }
228
229
230 /**********************************************************************
231 *  This is the callback function that is called by C engine for *all* *
232 *  php methods. This then calls the user callback funcs which require *
233 *  xmlrpcmsg for input and return xmlrpcresp.                         *
234 *                                                                     *
235 *  This function converts between native php types which are          *
236 *  sent/expected by C engine, and the objects which are used          *
237 *  by user funcs.  kind of ugly/slow, but necessary.                  *
238 **********************************************************************/
239 function xmlrpc_user_func_wrapper_cb($methodname, $params, $method_map) {
240    global $xmlrpcerr;
241    $user_func = $method_map[$methodname]['function'];
242
243    if ($user_func) {
244       // create msg from methodname and params.
245       $msg = new xmlrpcmsg($methodname);
246       foreach($params as $param) {
247          $msg->addParam(php_to_val($param));
248       }
249       
250       // call user func.
251       $rpc_resp = $user_func($msg);
252
253       // translate user func response into php values.
254       if (is_object($rpc_resp)) {
255          if ($rpc_resp->faultCode()) {
256             return xu_fault_code($rpc_resp->faultCode(), $rpc_resp->faultString());
257          }
258          return val_to_php($rpc_resp->value());
259       } else {
260          return xu_fault_code( $xmlrpcerr["invalid_return"], $xmlrpcstr["invalid_return"]);
261       }
262    }
263    return xu_fault_code( $xmlrpcerr["unknown_method"], $xmlrpcstr["unknown_method"]);
264 }
265
266 $_xmlrpc_debuginfo='';
267 function xmlrpc_debugmsg($m)
268 {
269     global $_xmlrpc_debuginfo;
270     $_xmlrpc_debuginfo=$_xmlrpc_debuginfo . $m . "\n";
271
272 ?>