source: trunk/phpgwapi/inc/class.soap_server.inc.php @ 2

Revision 2, 13.2 KB checked in by niltonneto, 17 years ago (diff)

Removida todas as tags usadas pelo CVS ($Id, $Source).
Primeira versão no CVS externo.

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2// SOAP server class
3
4// for example usage, see the test_server.php file.
5
6        class soap_server
7        {
8                function soap_server($data='',$serviceNow=False)
9                {
10                        // create empty dispatch map
11                        $this->dispatch_map = array();
12                        $this->debug_flag = True;
13                        $this->debug_str = '';
14                        $this->headers = '';
15                        $this->request = '';
16                        $this->result = 'successful';
17                        $this->fault = false;
18                        $this->fault_code = '';
19                        $this->fault_str = '';
20                        $this->fault_actor = '';
21
22                        if($serviceNow == 1)
23                        {
24                                $this->service($data);
25                        }
26                }
27
28                // parses request and posts response
29                function service($data)
30                {
31                        // $response is a soap_msg object
32                        $response = $this->parseRequest($data);
33                        $this->debug("parsed request and got an object of this class '".get_class($response)."'");
34                        $this->debug("server sending...");
35                        // pass along the debug string
36                        if($this->debug_flag)
37                        {
38                                $response->debug($this->debug_str);
39                        }
40                        $payload = $response->serialize();
41                        // print headers
42                        if($this->fault)
43                        {
44                                $header[] = "HTTP/1.0 500 Internal Server Error\r\n";
45                        }
46                        else
47                        {
48                                $header[] = "HTTP/1.0 200 OK\r\n";
49                                $header[] = "Status: 200\r\n";
50                        }
51                        $header[] = "Server: SOAPx4 Server v0.344359s\r\n";
52                        $header[] = "Connection: Close\r\n";
53                        $header[] = "Content-Type: text/xml; charset=UTF-8\r\n";
54                        $header[] = "Content-Length: ".strlen($payload)."\r\n\r\n";
55                        reset($header);
56                        foreach($header as $hdr)
57                        {
58                                header($hdr);
59                        }
60                        print $payload;
61                }
62
63                function parseRequest($data="")
64                {
65                        global $HTTP_SERVER_VARS;
66
67                        $this->debug("entering parseRequest() on ".date("H:i Y-m-d"));
68                        $request_uri = $HTTP_SERVER_VARS["REQUEST_URI"];
69                        $this->debug("request uri: $request_uri");
70                        // get headers
71                        $headers_array = getallheaders();
72                        foreach($headers_array as $k=>$v)
73                        {
74                                $dump .= "$k: $v\r\n";
75                        }
76                        $dump .= "\r\n\r\n".$data;
77                        $this->headers = $headers_array;
78                        $this->request = $dump;
79
80                        // get SOAPAction header -> methodname
81                        if($headers_array["SOAPAction"])
82                        {
83                                $action = str_replace('"','',$headers_array["SOAPAction"]);
84                                if(ereg("^urn:",$action))
85                                {
86                                        $this->service = substr($action,4);
87                                }
88                                elseif(ereg(".php",$action))
89                                {
90                                        $this->service = ereg_replace('"|/','',substr(strrchr($action,".php"),4,strlen(strrchr($action,"/"))));
91                                }
92                                $this->debug("got service: $this->service");
93                        }
94                        else
95                        {
96                                // throw a fault if no soapaction
97                                $this->debug("ERROR: no SOAPAction header found");
98                        }
99                        // NOTE:::: throw a fault for no/bad soapaction here?
100
101                        // parse response, get soap parser obj
102                        $parser = CreateObject('phpgwapi.soap_parser',$data);
103                        // get/set methodname
104                        $this->methodname = $parser->root_struct_name;
105                        $this->debug("method name: $this->methodname");
106
107                        // does method exist?
108                        $test = ereg_replace("\.",'_',$this->methodname);
109                        if(function_exists($test))
110                        {
111                                $method = $this->methodname = $test;
112                                $this->debug("method '$this->methodname' exists");
113                        }
114                        else
115                        {
116                                /* egroupware customization - createobject based on methodname */
117                                list($app,$class,$method) = explode('.',$this->methodname);
118                                if(ereg("^service",$app))
119                                {
120                                        $args  = $class;
121                                        $class = 'service';
122                                        $app   = 'phpgwapi';
123                                        $obj   = CreateObject(sprintf('%s.%s',$app,$class),$args);
124                                        unset($args);
125                                }
126                                else
127                                {
128                                        $obj = CreateObject(sprintf('%s.%s',$app,$class));
129                                }
130                                $this->debug('app: ' . $app . ', class: ' . $class . ', method: ' . $method);
131                                /*
132                                // "method not found" fault here
133                                $this->debug("method '$obj->method' not found!");
134                                $this->result = "fault: method not found";
135                                $this->make_fault("Server","method '$obj->method' not defined in service '$this->service'");
136                                return $this->fault();
137                                */
138                        }
139
140                        // if fault occurred during message parsing
141                        if($parser->fault())
142                        {
143                                // parser debug
144                                $this->debug($parser->debug_str);
145                                $this->result = "fault: error in msg parsing or eval";
146                                $this->make_fault("Server","error in msg parsing or eval:\n".$parser->get_response());
147                                // return soapresp
148                                return $this->fault();
149                                // else successfully parsed request into soapval object
150                        }
151                        else
152                        {
153                                // get eval_str
154                                $this->debug("calling parser->get_response()");
155                                // evaluate it, getting back a soapval object
156                                if(!$request_val = $parser->get_response())
157                                {
158                                        return $this->fault();
159                                }
160                                // parser debug
161                                $this->debug($parser->debug_str);
162                                if(get_class($request_val) == "soapval")
163                                {
164                                        if (is_object($obj))
165                                        {
166                                                /* Add the function to the server map */
167                                                $in  = "array('" . implode("','",$obj->soap_functions[$method]['in']) . "')";
168                                                $out = "array('" . implode("','",$obj->soap_functions[$method]['out']) . "')";
169                                                $evalmap  = "\$this->add_to_map(\$this->methodname,$in,$out);";
170                                                eval($evalmap);
171                                        }
172                                        /* verify that soapval objects in request match the methods signature */
173                                        if($this->verify_method($request_val))
174                                        {
175                                                $this->debug("request data - name: $request_val->name, type: $request_val->type, value: $request_val->value");
176                                                if($this->input_value)
177                                                {
178                                                        /* decode the soapval object, and pass resulting values to the requested method */
179                                                        if(!$request_data = $request_val->decode())
180                                                        {
181                                                                $this->make_fault("Server","Unable to decode response from soapval object into native php type.");
182                                                                return $this->fault();
183                                                        }
184                                                        $this->debug("request data: $request_data");
185                                                }
186
187                                                /* if there are return values */
188                                                if($this->return_type = $this->get_return_type())
189                                                {
190                                                        $this->debug("got return type: '$this->return_type'");
191                                                        /* if there are parameters to pass */
192                                                        if($request_data)
193                                                        {
194                                                                if (is_object($obj))
195                                                                {
196                                                                        $code = "\$method_response = call_user_method($method,$obj,";
197                                                                        $this->debug("about to call object method '$class\-\>$method' with args");
198                                                                }
199                                                                else
200                                                                {
201                                                                        $code = '$method_response = ' . $this->methodname . "('";
202                                                                        $args = implode("','",$request_data['return']);
203                                                                        $this->debug("about to call method '$this->methodname' with args: $args");
204                                                                }
205                                                                /* call method with parameters */
206                                                                $code .= implode("','",$request_data['return']);
207                                                                /*
208                                                                while(list($x,$y) = each($request_data))
209                                                                {
210                                                                        $code .= "\$request_data[$x]" . ',';
211                                                                }
212                                                                $code = substr($code,0,-1) .");";
213                                                                */
214                                                                $code .= "');";
215                                                                $this->debug('CODE: ' . $code);
216                                                                if(eval($code))
217                                                                {
218                                                                        if (is_object($obj))
219                                                                        {
220                                                                                $this->make_fault("Server","Object method call failed for '$class\-\>$method' with params: ".join(',',$request_data));
221                                                                        }
222                                                                        else
223                                                                        {
224                                                                                $this->make_fault("Server","Method call failed for '$this->methodname' with params: ".join(',',$request_data));
225                                                                        }
226                                                                        return $this->fault();
227                                                                }
228                                                                $this->debug('Response: ' . $method_response);
229                                                                //                                                      _debug_array($method_response);
230                                                        }
231                                                        else
232                                                        {
233                                                                /* call method w/ no parameters */
234                                                                if (is_object($obj))
235                                                                {
236                                                                        $this->debug("about to call object method '$obj\-\>$method'");
237                                                                        if(!$method_response = call_user_method($method,$obj))
238                                                                        {
239                                                                                $this->make_fault("Server","Method call failed for '$obj->method' with no params");
240                                                                                return $this->fault();
241                                                                        }
242                                                                }
243                                                                else
244                                                                {
245                                                                        $this->debug("about to call method '$this->methodname'");
246                                                                        if(!$method_response = call_user_func($this->methodname))
247                                                                        {
248                                                                                $this->make_fault("Server","Method call failed for '$this->methodname' with no params");
249                                                                                return $this->fault();
250                                                                        }
251                                                                }
252                                                        }
253                                                        /* no return values */
254                                                }
255                                                else
256                                                {
257                                                        if($request_data)
258                                                        {
259                                                                /* call method with parameters */
260                                                                $code = "\$method_response = call_user_method(\$method,\$obj,";
261                                                                while(list($x,$y) = each($request_data))
262                                                                {
263                                                                        $code .= "\$request_data[$x]" . ',';
264                                                                }
265                                                                $code = substr($code,0,-1) .");";
266                                                                $this->debug("about to call object method '$obj\-\>$method'");
267                                                                eval($code);
268                                                        }
269                                                        else
270                                                        {
271                                                                /* call method w/ no parameters */
272                                                                if(is_object($obj))
273                                                                {
274                                                                        $this->debug("about to call object method '$obj\-\>$method'");
275                                                                        call_user_method($method,$obj);
276                                                                }
277                                                                else
278                                                                {
279                                                                        $this->debug("about to call method '$method'");
280                                                                        call_user_func($method);
281                                                                }
282                                                        }
283                                                }
284
285                                                /* create soap_val object w/ return values from method, use method signature to determine type */
286                                                if(get_class($method_response) != 'soapval')
287                                                {
288                                                        $return_val = CreateObject('phpgwapi.soapval',$method,$this->return_type,$method_response);
289                                                }
290                                                else
291                                                {
292                                                        $return_val = $method_response;
293                                                }
294                                                $this->debug($return_val->debug_str);
295                                                /* response object is a soap_msg object */
296                                                $return_msg =  CreateObject('phpgwapi.soapmsg',$method.'Response',array($return_val),$this->service);
297                                                if($this->debug_flag)
298                                                {
299                                                        $return_msg->debug_flag = true;
300                                                }
301                                                $this->result = "successful";
302                                                return $return_msg;
303                                        }
304                                        else
305                                        {
306                                                // debug
307                                                $this->debug("ERROR: request not verified against method signature");
308                                                $this->result = "fault: request failed validation against method signature";
309                                                // return soapresp
310                                                return $this->fault();
311                                        }
312                                }
313                                else
314                                {
315                                        // debug
316                                        $this->debug("ERROR: parser did not return soapval object: $request_val ".get_class($request_val));
317                                        $this->result = "fault: parser did not return soapval object: $request_val";
318                                        // return fault
319                                        $this->make_fault("Server","parser did not return soapval object: $request_val");
320                                        return $this->fault();
321                                }
322                        }
323                }
324
325                function verify_method($request)
326                {
327                        //return true;
328                        $this->debug("entered verify_method() w/ request name: ".$request->name);
329                        $params = $request->value;
330                        // if there are input parameters required...
331                        if($sig = $this->dispatch_map[$this->methodname]["in"])
332                        {
333                                $this->input_value = count($sig);
334                                if(is_array($params))
335                                {
336                                        $this->debug("entered verify_method() with ".count($params)." parameters");
337                                        foreach($params as $v)
338                                        {
339                                                $this->debug("param '$v->name' of type '$v->type'");
340                                        }
341                                        // validate the number of parameters
342                                        if(count($params) == count($sig))
343                                        {
344                                                $this->debug("got correct number of parameters: ".count($sig));
345                                                // make array of param types
346                                                foreach($params as $param)
347                                                {
348                                                        $p[] = strtolower($param->type);
349                                                }
350                                                // validate each param's type
351                                                for($i=0; $i < count($p); $i++)
352                                                {
353                                                        // type not match
354                                                        if(strtolower($sig[$i]) != strtolower($p[$i]))
355                                                        {
356                                                                $this->debug("mismatched parameter types: $sig[$i] != $p[$i]");
357                                                                $this->make_fault("Client","soap request contained mismatching parameters of name $v->name had type $p[$i], which did not match signature's type: $sig[$i]");
358                                                                return false;
359                                                        }
360                                                        $this->debug("parameter type match: $sig[$i] = $p[$i]");
361                                                }
362                                                return true;
363                                                // oops, wrong number of paramss
364                                        }
365                                        else
366                                        {
367                                                $this->debug("oops, wrong number of parameter!");
368                                                $this->make_fault("Client","soap request contained incorrect number of parameters. method '$this->methodname' required ".count($sig)." and request provided ".count($params));
369                                                return false;
370                                        }
371                                        // oops, no params...
372                                }
373                                else
374                                {
375                                        $this->debug("oops, no parameters sent! Method '$this->methodname' requires ".count($sig)." input parameters!");
376                                        $this->make_fault("Client","soap request contained incorrect number of parameters. method '$this->methodname' requires ".count($sig)." parameters, and request provided none");
377                                        return false;
378                                }
379                                // no params
380                        }
381                        elseif( (count($params)==0) && (count($sig) <= 1) )
382                        {
383                                $this->input_values = 0;
384                                return true;
385                        }
386                        else
387                        {
388                                //$this->debug("well, request passed parameters to a method that requires none?");
389                                //$this->make_fault("Client","method '$this->methodname' requires no parameters. The request passed in ".count($params).": ".@implode(" param: ",$params) );
390                                return true;
391                        }
392                }
393
394                // get string return type from dispatch map
395                function get_return_type()
396                {
397                        if(count($this->dispatch_map[$this->methodname]["out"]) >= 1)
398                        {
399                                $type = array_shift($this->dispatch_map[$this->methodname]["out"]);
400                                $this->debug("got return type from dispatch map: '$type'");
401                                return $type;
402                        }
403                        return false;
404                }
405
406                // dbg
407                function debug($string)
408                {
409                        if($this->debug_flag)
410                        {
411                                $this->debug_str .= "$string\n";
412                        }
413                }
414
415                // add a method to the dispatch map
416                function add_to_map($methodname,$in,$out)
417                {
418                        $this->dispatch_map[$methodname]["in"] = $in;
419                        $this->dispatch_map[$methodname]["out"] = $out;
420                }
421
422                // set up a fault
423                function fault()
424                {
425                        return CreateObject('phpgwapi.soapmsg',
426                        "Fault",
427                        array(
428                                "faultcode" => $this->fault_code,
429                                "faultstring" => $this->fault_str,
430                                "faultactor" => $this->fault_actor,
431                                "faultdetail" => $this->fault_detail.$this->debug_str
432                        ),
433                        "http://schemas.xmlphpgwapi.org/soap/envelope/"
434                );
435        }
436
437        function make_fault($fault_code,$fault_string)
438        {
439                $this->fault_code = $fault_code;
440                $this->fault_str = $fault_string;
441                $this->fault = true;
442        }
443}
444?>
Note: See TracBrowser for help on using the repository browser.