]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/XMLRPC/xmlrpcs_emu.inc
More help with the new native xmlrpc lib. no warnings, no user cookie on xmlrpc.
[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: xmlrpcs_emu.inc,v 1.2 2004-12-10 02:36:43 rurban Exp $
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
174       // call server
175       $payload = xmlrpc_server_call_method($this->xmlrpc_server, $data, $this->dmap, 
176                                            array('output_type' => "xml", 'version' => "xmlrpc"));
177       Header("Content-type: text/xml\nContent-length: " . strlen($payload));
178       echo $payload;
179    }
180
181    // private. no equivalent in C library (yet)
182    function verifySignature($in, $sig) {
183       return "verifySignature not supported";
184    }
185
186    // public. this used to be called by service(). 
187    // it's no longer necessary, but we keep it around in case 
188    // people are calling it directly from applications.
189    function parseRequest($data="") {
190       global $_xh,$HTTP_RAW_POST_DATA;
191
192       global $xmlrpcerr, $xmlrpcstr, $xmlrpcerrxml, $xmlrpc_defencoding;
193
194       if ($data == "") {
195          $data = $HTTP_RAW_POST_DATA;
196       }
197
198       // call server
199       $php_val = xmlrpc_server_call_method($this->xmlrpc_server, $data, $this->dmap, 
200                                            array('output_type' => "php", 'version' => "xmlrpc"));
201
202       /* check for fault */
203       if (is_array($php_val) && isset($php_val['faultCode'])) {
204          $fc = $php_val['faultCode'];
205          $fs = $php_val['faultString'];
206       } else {
207          $rpc_val = php_to_val($php_val);
208       }
209       $response = new xmlrpcresp($rpc_val, $fc, $fs);
210
211       return $response;
212    }
213
214    // public.  test routine.
215    function echoInput() {
216       global $HTTP_RAW_POST_DATA;
217
218       // a debugging routine: just echos back the input
219       // packet as a string value
220
221       $r = new xmlrpcresp;
222       $r->xv = new xmlrpcval( "'Aha said I: '" . $HTTP_RAW_POST_DATA, "string");
223       print $r->serialize();
224    }
225 }
226
227
228 /**********************************************************************
229 *  This is the callback function that is called by C engine for *all* *
230 *  php methods. This then calls the user callback funcs which require *
231 *  xmlrpcmsg for input and return xmlrpcresp.                         *
232 *                                                                     *
233 *  This function converts between native php types which are          *
234 *  sent/expected by C engine, and the objects which are used          *
235 *  by user funcs.  kind of ugly/slow, but necessary.                  *
236 **********************************************************************/
237 function xmlrpc_user_func_wrapper_cb($methodname, $params, $method_map) {
238    global $xmlrpcerr;
239    $user_func = $method_map[$methodname]['function'];
240
241    if ($user_func) {
242       // create msg from methodname and params.
243       $msg = new xmlrpcmsg($methodname);
244       foreach($params as $param) {
245          $msg->addParam(php_to_val($param));
246       }
247       
248       // call user func.
249       $rpc_resp = $user_func($msg);
250
251       // translate user func response into php values.
252       if (is_object($rpc_resp)) {
253          if ($rpc_resp->faultCode()) {
254             return xu_fault_code($rpc_resp->faultCode(), $rpc_resp->faultString());
255          }
256          return val_to_php($rpc_resp->value());
257       } else {
258          return xu_fault_code( $xmlrpcerr["invalid_return"], $xmlrpcstr["invalid_return"]);
259       }
260    }
261    return xu_fault_code( $xmlrpcerr["unknown_method"], $xmlrpcstr["unknown_method"]);
262 }
263
264 $_xmlrpc_debuginfo='';
265 function xmlrpc_debugmsg($m)
266 {
267     global $_xmlrpc_debuginfo;
268     $_xmlrpc_debuginfo=$_xmlrpc_debuginfo . $m . "\n";
269
270 ?>