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