[ Index ] |
|
Code source de Mantis 1.1.0rc3 |
1 <?php 2 3 4 5 6 /** 7 * 8 * nusoap_server allows the user to create a SOAP server 9 * that is capable of receiving messages and returning responses 10 * 11 * @author Dietrich Ayala <dietrich@ganx4.com> 12 * @author Scott Nichol <snichol@users.sourceforge.net> 13 * @version $Id: class.soap_server.php,v 1.58 2007/10/30 18:50:30 snichol Exp $ 14 * @access public 15 */ 16 class nusoap_server extends nusoap_base { 17 /** 18 * HTTP headers of request 19 * @var array 20 * @access private 21 */ 22 var $headers = array(); 23 /** 24 * HTTP request 25 * @var string 26 * @access private 27 */ 28 var $request = ''; 29 /** 30 * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) 31 * @var string 32 * @access public 33 */ 34 var $requestHeaders = ''; 35 /** 36 * SOAP Headers from request (parsed) 37 * @var mixed 38 * @access public 39 */ 40 var $requestHeader = NULL; 41 /** 42 * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) 43 * @var string 44 * @access public 45 */ 46 var $document = ''; 47 /** 48 * SOAP payload for request (text) 49 * @var string 50 * @access public 51 */ 52 var $requestSOAP = ''; 53 /** 54 * requested method namespace URI 55 * @var string 56 * @access private 57 */ 58 var $methodURI = ''; 59 /** 60 * name of method requested 61 * @var string 62 * @access private 63 */ 64 var $methodname = ''; 65 /** 66 * method parameters from request 67 * @var array 68 * @access private 69 */ 70 var $methodparams = array(); 71 /** 72 * SOAP Action from request 73 * @var string 74 * @access private 75 */ 76 var $SOAPAction = ''; 77 /** 78 * character set encoding of incoming (request) messages 79 * @var string 80 * @access public 81 */ 82 var $xml_encoding = ''; 83 /** 84 * toggles whether the parser decodes element content w/ utf8_decode() 85 * @var boolean 86 * @access public 87 */ 88 var $decode_utf8 = true; 89 90 /** 91 * HTTP headers of response 92 * @var array 93 * @access public 94 */ 95 var $outgoing_headers = array(); 96 /** 97 * HTTP response 98 * @var string 99 * @access private 100 */ 101 var $response = ''; 102 /** 103 * SOAP headers for response (text or array of soapval or associative array) 104 * @var mixed 105 * @access public 106 */ 107 var $responseHeaders = ''; 108 /** 109 * SOAP payload for response (text) 110 * @var string 111 * @access private 112 */ 113 var $responseSOAP = ''; 114 /** 115 * method return value to place in response 116 * @var mixed 117 * @access private 118 */ 119 var $methodreturn = false; 120 /** 121 * whether $methodreturn is a string of literal XML 122 * @var boolean 123 * @access public 124 */ 125 var $methodreturnisliteralxml = false; 126 /** 127 * SOAP fault for response (or false) 128 * @var mixed 129 * @access private 130 */ 131 var $fault = false; 132 /** 133 * text indication of result (for debugging) 134 * @var string 135 * @access private 136 */ 137 var $result = 'successful'; 138 139 /** 140 * assoc array of operations => opData; operations are added by the register() 141 * method or by parsing an external WSDL definition 142 * @var array 143 * @access private 144 */ 145 var $operations = array(); 146 /** 147 * wsdl instance (if one) 148 * @var mixed 149 * @access private 150 */ 151 var $wsdl = false; 152 /** 153 * URL for WSDL (if one) 154 * @var mixed 155 * @access private 156 */ 157 var $externalWSDLURL = false; 158 /** 159 * whether to append debug to response as XML comment 160 * @var boolean 161 * @access public 162 */ 163 var $debug_flag = false; 164 165 166 /** 167 * constructor 168 * the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. 169 * 170 * @param mixed $wsdl file path or URL (string), or wsdl instance (object) 171 * @access public 172 */ 173 function nusoap_server($wsdl=false){ 174 parent::nusoap_base(); 175 // turn on debugging? 176 global $debug; 177 global $HTTP_SERVER_VARS; 178 179 if (isset($_SERVER)) { 180 $this->debug("_SERVER is defined:"); 181 $this->appendDebug($this->varDump($_SERVER)); 182 } elseif (isset($HTTP_SERVER_VARS)) { 183 $this->debug("HTTP_SERVER_VARS is defined:"); 184 $this->appendDebug($this->varDump($HTTP_SERVER_VARS)); 185 } else { 186 $this->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined."); 187 } 188 189 if (isset($debug)) { 190 $this->debug("In nusoap_server, set debug_flag=$debug based on global flag"); 191 $this->debug_flag = $debug; 192 } elseif (isset($_SERVER['QUERY_STRING'])) { 193 $qs = explode('&', $_SERVER['QUERY_STRING']); 194 foreach ($qs as $v) { 195 if (substr($v, 0, 6) == 'debug=') { 196 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #1"); 197 $this->debug_flag = substr($v, 6); 198 } 199 } 200 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { 201 $qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']); 202 foreach ($qs as $v) { 203 if (substr($v, 0, 6) == 'debug=') { 204 $this->debug("In nusoap_server, set debug_flag=" . substr($v, 6) . " based on query string #2"); 205 $this->debug_flag = substr($v, 6); 206 } 207 } 208 } 209 210 // wsdl 211 if($wsdl){ 212 $this->debug("In nusoap_server, WSDL is specified"); 213 if (is_object($wsdl) && (get_class($wsdl) == 'wsdl')) { 214 $this->wsdl = $wsdl; 215 $this->externalWSDLURL = $this->wsdl->wsdl; 216 $this->debug('Use existing wsdl instance from ' . $this->externalWSDLURL); 217 } else { 218 $this->debug('Create wsdl from ' . $wsdl); 219 $this->wsdl = new wsdl($wsdl); 220 $this->externalWSDLURL = $wsdl; 221 } 222 $this->appendDebug($this->wsdl->getDebug()); 223 $this->wsdl->clearDebug(); 224 if($err = $this->wsdl->getError()){ 225 die('WSDL ERROR: '.$err); 226 } 227 } 228 } 229 230 /** 231 * processes request and returns response 232 * 233 * @param string $data usually is the value of $HTTP_RAW_POST_DATA 234 * @access public 235 */ 236 function service($data){ 237 global $HTTP_SERVER_VARS; 238 239 if (isset($_SERVER['QUERY_STRING'])) { 240 $qs = $_SERVER['QUERY_STRING']; 241 } elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) { 242 $qs = $HTTP_SERVER_VARS['QUERY_STRING']; 243 } else { 244 $qs = ''; 245 } 246 $this->debug("In service, query string=$qs"); 247 248 if (ereg('wsdl', $qs) ){ 249 $this->debug("In service, this is a request for WSDL"); 250 if($this->externalWSDLURL){ 251 if (strpos($this->externalWSDLURL,"://")!==false) { // assume URL 252 header('Location: '.$this->externalWSDLURL); 253 } else { // assume file 254 header("Content-Type: text/xml\r\n"); 255 $fp = fopen($this->externalWSDLURL, 'r'); 256 fpassthru($fp); 257 } 258 } elseif ($this->wsdl) { 259 header("Content-Type: text/xml; charset=ISO-8859-1\r\n"); 260 print $this->wsdl->serialize($this->debug_flag); 261 if ($this->debug_flag) { 262 $this->debug('wsdl:'); 263 $this->appendDebug($this->varDump($this->wsdl)); 264 print $this->getDebugAsXMLComment(); 265 } 266 } else { 267 header("Content-Type: text/html; charset=ISO-8859-1\r\n"); 268 print "This service does not provide WSDL"; 269 } 270 } elseif ($data == '' && $this->wsdl) { 271 $this->debug("In service, there is no data, so return Web description"); 272 print $this->wsdl->webDescription(); 273 } else { 274 $this->debug("In service, invoke the request"); 275 $this->parse_request($data); 276 if (! $this->fault) { 277 $this->invoke_method(); 278 } 279 if (! $this->fault) { 280 $this->serialize_return(); 281 } 282 $this->send_response(); 283 } 284 } 285 286 /** 287 * parses HTTP request headers. 288 * 289 * The following fields are set by this function (when successful) 290 * 291 * headers 292 * request 293 * xml_encoding 294 * SOAPAction 295 * 296 * @access private 297 */ 298 function parse_http_headers() { 299 global $HTTP_SERVER_VARS; 300 301 $this->request = ''; 302 $this->SOAPAction = ''; 303 if(function_exists('getallheaders')){ 304 $this->debug("In parse_http_headers, use getallheaders"); 305 $headers = getallheaders(); 306 foreach($headers as $k=>$v){ 307 $k = strtolower($k); 308 $this->headers[$k] = $v; 309 $this->request .= "$k: $v\r\n"; 310 $this->debug("$k: $v"); 311 } 312 // get SOAPAction header 313 if(isset($this->headers['soapaction'])){ 314 $this->SOAPAction = str_replace('"','',$this->headers['soapaction']); 315 } 316 // get the character encoding of the incoming request 317 if(isset($this->headers['content-type']) && strpos($this->headers['content-type'],'=')){ 318 $enc = str_replace('"','',substr(strstr($this->headers["content-type"],'='),1)); 319 if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){ 320 $this->xml_encoding = strtoupper($enc); 321 } else { 322 $this->xml_encoding = 'US-ASCII'; 323 } 324 } else { 325 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 326 $this->xml_encoding = 'ISO-8859-1'; 327 } 328 } elseif(isset($_SERVER) && is_array($_SERVER)){ 329 $this->debug("In parse_http_headers, use _SERVER"); 330 foreach ($_SERVER as $k => $v) { 331 if (substr($k, 0, 5) == 'HTTP_') { 332 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); 333 } else { 334 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); 335 } 336 if ($k == 'soapaction') { 337 // get SOAPAction header 338 $k = 'SOAPAction'; 339 $v = str_replace('"', '', $v); 340 $v = str_replace('\\', '', $v); 341 $this->SOAPAction = $v; 342 } else if ($k == 'content-type') { 343 // get the character encoding of the incoming request 344 if (strpos($v, '=')) { 345 $enc = substr(strstr($v, '='), 1); 346 $enc = str_replace('"', '', $enc); 347 $enc = str_replace('\\', '', $enc); 348 if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) { 349 $this->xml_encoding = strtoupper($enc); 350 } else { 351 $this->xml_encoding = 'US-ASCII'; 352 } 353 } else { 354 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 355 $this->xml_encoding = 'ISO-8859-1'; 356 } 357 } 358 $this->headers[$k] = $v; 359 $this->request .= "$k: $v\r\n"; 360 $this->debug("$k: $v"); 361 } 362 } elseif (is_array($HTTP_SERVER_VARS)) { 363 $this->debug("In parse_http_headers, use HTTP_SERVER_VARS"); 364 foreach ($HTTP_SERVER_VARS as $k => $v) { 365 if (substr($k, 0, 5) == 'HTTP_') { 366 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5)); 367 } else { 368 $k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k); 369 } 370 if ($k == 'soapaction') { 371 // get SOAPAction header 372 $k = 'SOAPAction'; 373 $v = str_replace('"', '', $v); 374 $v = str_replace('\\', '', $v); 375 $this->SOAPAction = $v; 376 } else if ($k == 'content-type') { 377 // get the character encoding of the incoming request 378 if (strpos($v, '=')) { 379 $enc = substr(strstr($v, '='), 1); 380 $enc = str_replace('"', '', $enc); 381 $enc = str_replace('\\', '', $enc); 382 if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) { 383 $this->xml_encoding = strtoupper($enc); 384 } else { 385 $this->xml_encoding = 'US-ASCII'; 386 } 387 } else { 388 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 389 $this->xml_encoding = 'ISO-8859-1'; 390 } 391 } 392 $this->headers[$k] = $v; 393 $this->request .= "$k: $v\r\n"; 394 $this->debug("$k: $v"); 395 } 396 } else { 397 $this->debug("In parse_http_headers, HTTP headers not accessible"); 398 $this->setError("HTTP headers not accessible"); 399 } 400 } 401 402 /** 403 * parses a request 404 * 405 * The following fields are set by this function (when successful) 406 * 407 * headers 408 * request 409 * xml_encoding 410 * SOAPAction 411 * request 412 * requestSOAP 413 * methodURI 414 * methodname 415 * methodparams 416 * requestHeaders 417 * document 418 * 419 * This sets the fault field on error 420 * 421 * @param string $data XML string 422 * @access private 423 */ 424 function parse_request($data='') { 425 $this->debug('entering parse_request()'); 426 $this->parse_http_headers(); 427 $this->debug('got character encoding: '.$this->xml_encoding); 428 // uncompress if necessary 429 if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') { 430 $this->debug('got content encoding: ' . $this->headers['content-encoding']); 431 if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') { 432 // if decoding works, use it. else assume data wasn't gzencoded 433 if (function_exists('gzuncompress')) { 434 if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) { 435 $data = $degzdata; 436 } elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) { 437 $data = $degzdata; 438 } else { 439 $this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data'); 440 return; 441 } 442 } else { 443 $this->fault('SOAP-ENV:Client', 'This Server does not support compressed data'); 444 return; 445 } 446 } 447 } 448 $this->request .= "\r\n".$data; 449 $data = $this->parseRequest($this->headers, $data); 450 $this->requestSOAP = $data; 451 $this->debug('leaving parse_request'); 452 } 453 454 /** 455 * invokes a PHP function for the requested SOAP method 456 * 457 * The following fields are set by this function (when successful) 458 * 459 * methodreturn 460 * 461 * Note that the PHP function that is called may also set the following 462 * fields to affect the response sent to the client 463 * 464 * responseHeaders 465 * outgoing_headers 466 * 467 * This sets the fault field on error 468 * 469 * @access private 470 */ 471 function invoke_method() { 472 $this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction); 473 474 if ($this->wsdl) { 475 if ($this->opData = $this->wsdl->getOperationData($this->methodname)) { 476 $this->debug('in invoke_method, found WSDL operation=' . $this->methodname); 477 $this->appendDebug('opData=' . $this->varDump($this->opData)); 478 } elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) { 479 // Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element 480 $this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']); 481 $this->appendDebug('opData=' . $this->varDump($this->opData)); 482 $this->methodname = $this->opData['name']; 483 } else { 484 $this->debug('in invoke_method, no WSDL for operation=' . $this->methodname); 485 $this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service"); 486 return; 487 } 488 } else { 489 $this->debug('in invoke_method, no WSDL to validate method'); 490 } 491 492 // if a . is present in $this->methodname, we see if there is a class in scope, 493 // which could be referred to. We will also distinguish between two deliminators, 494 // to allow methods to be called a the class or an instance 495 $class = ''; 496 $method = ''; 497 if (strpos($this->methodname, '..') > 0) { 498 $delim = '..'; 499 } else if (strpos($this->methodname, '.') > 0) { 500 $delim = '.'; 501 } else { 502 $delim = ''; 503 } 504 505 if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 && 506 class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) { 507 // get the class and method name 508 $class = substr($this->methodname, 0, strpos($this->methodname, $delim)); 509 $method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim)); 510 $this->debug("in invoke_method, class=$class method=$method delim=$delim"); 511 } 512 513 // does method exist? 514 if ($class == '') { 515 if (!function_exists($this->methodname)) { 516 $this->debug("in invoke_method, function '$this->methodname' not found!"); 517 $this->result = 'fault: method not found'; 518 $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service"); 519 return; 520 } 521 } else { 522 $method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method; 523 if (!in_array($method_to_compare, get_class_methods($class))) { 524 $this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!"); 525 $this->result = 'fault: method not found'; 526 $this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service"); 527 return; 528 } 529 } 530 531 // evaluate message, getting back parameters 532 // verify that request parameters match the method's signature 533 if(! $this->verify_method($this->methodname,$this->methodparams)){ 534 // debug 535 $this->debug('ERROR: request not verified against method signature'); 536 $this->result = 'fault: request failed validation against method signature'; 537 // return fault 538 $this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service."); 539 return; 540 } 541 542 // if there are parameters to pass 543 $this->debug('in invoke_method, params:'); 544 $this->appendDebug($this->varDump($this->methodparams)); 545 $this->debug("in invoke_method, calling '$this->methodname'"); 546 if (!function_exists('call_user_func_array')) { 547 if ($class == '') { 548 $this->debug('in invoke_method, calling function using eval()'); 549 $funcCall = "\$this->methodreturn = $this->methodname("; 550 } else { 551 if ($delim == '..') { 552 $this->debug('in invoke_method, calling class method using eval()'); 553 $funcCall = "\$this->methodreturn = ".$class."::".$method."("; 554 } else { 555 $this->debug('in invoke_method, calling instance method using eval()'); 556 // generate unique instance name 557 $instname = "\$inst_".time(); 558 $funcCall = $instname." = new ".$class."(); "; 559 $funcCall .= "\$this->methodreturn = ".$instname."->".$method."("; 560 } 561 } 562 if ($this->methodparams) { 563 foreach ($this->methodparams as $param) { 564 if (is_array($param) || is_object($param)) { 565 $this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available'); 566 return; 567 } 568 $funcCall .= "\"$param\","; 569 } 570 $funcCall = substr($funcCall, 0, -1); 571 } 572 $funcCall .= ');'; 573 $this->debug('in invoke_method, function call: '.$funcCall); 574 @eval($funcCall); 575 } else { 576 if ($class == '') { 577 $this->debug('in invoke_method, calling function using call_user_func_array()'); 578 $call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array() 579 } elseif ($delim == '..') { 580 $this->debug('in invoke_method, calling class method using call_user_func_array()'); 581 $call_arg = array ($class, $method); 582 } else { 583 $this->debug('in invoke_method, calling instance method using call_user_func_array()'); 584 $instance = new $class (); 585 $call_arg = array(&$instance, $method); 586 } 587 if (is_array($this->methodparams)) { 588 $this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams)); 589 } else { 590 $this->methodreturn = call_user_func_array($call_arg, array()); 591 } 592 } 593 $this->debug('in invoke_method, methodreturn:'); 594 $this->appendDebug($this->varDump($this->methodreturn)); 595 $this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn)); 596 } 597 598 /** 599 * serializes the return value from a PHP function into a full SOAP Envelope 600 * 601 * The following fields are set by this function (when successful) 602 * 603 * responseSOAP 604 * 605 * This sets the fault field on error 606 * 607 * @access private 608 */ 609 function serialize_return() { 610 $this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI); 611 // if fault 612 if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) { 613 $this->debug('got a fault object from method'); 614 $this->fault = $this->methodreturn; 615 return; 616 } elseif ($this->methodreturnisliteralxml) { 617 $return_val = $this->methodreturn; 618 // returned value(s) 619 } else { 620 $this->debug('got a(n) '.gettype($this->methodreturn).' from method'); 621 $this->debug('serializing return value'); 622 if($this->wsdl){ 623 if (sizeof($this->opData['output']['parts']) > 1) { 624 $this->debug('more than one output part, so use the method return unchanged'); 625 $opParams = $this->methodreturn; 626 } elseif (sizeof($this->opData['output']['parts']) == 1) { 627 $this->debug('exactly one output part, so wrap the method return in a simple array'); 628 // TODO: verify that it is not already wrapped! 629 //foreach ($this->opData['output']['parts'] as $name => $type) { 630 // $this->debug('wrap in element named ' . $name); 631 //} 632 $opParams = array($this->methodreturn); 633 } 634 $return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams); 635 $this->appendDebug($this->wsdl->getDebug()); 636 $this->wsdl->clearDebug(); 637 if($errstr = $this->wsdl->getError()){ 638 $this->debug('got wsdl error: '.$errstr); 639 $this->fault('SOAP-ENV:Server', 'unable to serialize result'); 640 return; 641 } 642 } else { 643 if (isset($this->methodreturn)) { 644 $return_val = $this->serialize_val($this->methodreturn, 'return'); 645 } else { 646 $return_val = ''; 647 $this->debug('in absence of WSDL, assume void return for backward compatibility'); 648 } 649 } 650 } 651 $this->debug('return value:'); 652 $this->appendDebug($this->varDump($return_val)); 653 654 $this->debug('serializing response'); 655 if ($this->wsdl) { 656 $this->debug('have WSDL for serialization: style is ' . $this->opData['style']); 657 if ($this->opData['style'] == 'rpc') { 658 $this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']); 659 if ($this->opData['output']['use'] == 'literal') { 660 // http://www.ws-i.org/Profiles/BasicProfile-1.1-2004-08-24.html R2735 says rpc/literal accessor elements should not be in a namespace 661 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; 662 } else { 663 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; 664 } 665 } else { 666 $this->debug('style is not rpc for serialization: assume document'); 667 $payload = $return_val; 668 } 669 } else { 670 $this->debug('do not have WSDL for serialization: assume rpc/encoded'); 671 $payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>"; 672 } 673 $this->result = 'successful'; 674 if($this->wsdl){ 675 //if($this->debug_flag){ 676 $this->appendDebug($this->wsdl->getDebug()); 677 // } 678 if (isset($opData['output']['encodingStyle'])) { 679 $encodingStyle = $opData['output']['encodingStyle']; 680 } else { 681 $encodingStyle = ''; 682 } 683 // Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces. 684 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle); 685 } else { 686 $this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders); 687 } 688 $this->debug("Leaving serialize_return"); 689 } 690 691 /** 692 * sends an HTTP response 693 * 694 * The following fields are set by this function (when successful) 695 * 696 * outgoing_headers 697 * response 698 * 699 * @access private 700 */ 701 function send_response() { 702 $this->debug('Enter send_response'); 703 if ($this->fault) { 704 $payload = $this->fault->serialize(); 705 $this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error"; 706 $this->outgoing_headers[] = "Status: 500 Internal Server Error"; 707 } else { 708 $payload = $this->responseSOAP; 709 // Some combinations of PHP+Web server allow the Status 710 // to come through as a header. Since OK is the default 711 // just do nothing. 712 // $this->outgoing_headers[] = "HTTP/1.0 200 OK"; 713 // $this->outgoing_headers[] = "Status: 200 OK"; 714 } 715 // add debug data if in debug mode 716 if(isset($this->debug_flag) && $this->debug_flag){ 717 $payload .= $this->getDebugAsXMLComment(); 718 } 719 $this->outgoing_headers[] = "Server: $this->title Server v$this->version"; 720 ereg('\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev); 721 $this->outgoing_headers[] = "X-SOAP-Server: $this->title/$this->version (".$rev[1].")"; 722 // Let the Web server decide about this 723 //$this->outgoing_headers[] = "Connection: Close\r\n"; 724 $payload = $this->getHTTPBody($payload); 725 $type = $this->getHTTPContentType(); 726 $charset = $this->getHTTPContentTypeCharset(); 727 $this->outgoing_headers[] = "Content-Type: $type" . ($charset ? '; charset=' . $charset : ''); 728 //begin code to compress payload - by John 729 // NOTE: there is no way to know whether the Web server will also compress 730 // this data. 731 if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) { 732 if (strstr($this->headers['accept-encoding'], 'gzip')) { 733 if (function_exists('gzencode')) { 734 if (isset($this->debug_flag) && $this->debug_flag) { 735 $payload .= "<!-- Content being gzipped -->"; 736 } 737 $this->outgoing_headers[] = "Content-Encoding: gzip"; 738 $payload = gzencode($payload); 739 } else { 740 if (isset($this->debug_flag) && $this->debug_flag) { 741 $payload .= "<!-- Content will not be gzipped: no gzencode -->"; 742 } 743 } 744 } elseif (strstr($this->headers['accept-encoding'], 'deflate')) { 745 // Note: MSIE requires gzdeflate output (no Zlib header and checksum), 746 // instead of gzcompress output, 747 // which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5) 748 if (function_exists('gzdeflate')) { 749 if (isset($this->debug_flag) && $this->debug_flag) { 750 $payload .= "<!-- Content being deflated -->"; 751 } 752 $this->outgoing_headers[] = "Content-Encoding: deflate"; 753 $payload = gzdeflate($payload); 754 } else { 755 if (isset($this->debug_flag) && $this->debug_flag) { 756 $payload .= "<!-- Content will not be deflated: no gzcompress -->"; 757 } 758 } 759 } 760 } 761 //end code 762 $this->outgoing_headers[] = "Content-Length: ".strlen($payload); 763 reset($this->outgoing_headers); 764 foreach($this->outgoing_headers as $hdr){ 765 header($hdr, false); 766 } 767 print $payload; 768 $this->response = join("\r\n",$this->outgoing_headers)."\r\n\r\n".$payload; 769 } 770 771 /** 772 * takes the value that was created by parsing the request 773 * and compares to the method's signature, if available. 774 * 775 * @param string $operation The operation to be invoked 776 * @param array $request The array of parameter values 777 * @return boolean Whether the operation was found 778 * @access private 779 */ 780 function verify_method($operation,$request){ 781 if(isset($this->wsdl) && is_object($this->wsdl)){ 782 if($this->wsdl->getOperationData($operation)){ 783 return true; 784 } 785 } elseif(isset($this->operations[$operation])){ 786 return true; 787 } 788 return false; 789 } 790 791 /** 792 * processes SOAP message received from client 793 * 794 * @param array $headers The HTTP headers 795 * @param string $data unprocessed request data from client 796 * @return mixed value of the message, decoded into a PHP type 797 * @access private 798 */ 799 function parseRequest($headers, $data) { 800 $this->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']); 801 if (!strstr($headers['content-type'], 'text/xml')) { 802 $this->setError('Request not of type text/xml'); 803 return false; 804 } 805 if (strpos($headers['content-type'], '=')) { 806 $enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1)); 807 $this->debug('Got response encoding: ' . $enc); 808 if(eregi('^(ISO-8859-1|US-ASCII|UTF-8)$',$enc)){ 809 $this->xml_encoding = strtoupper($enc); 810 } else { 811 $this->xml_encoding = 'US-ASCII'; 812 } 813 } else { 814 // should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1 815 $this->xml_encoding = 'ISO-8859-1'; 816 } 817 $this->debug('Use encoding: ' . $this->xml_encoding . ' when creating nusoap_parser'); 818 // parse response, get soap parser obj 819 $parser = new nusoap_parser($data,$this->xml_encoding,'',$this->decode_utf8); 820 // parser debug 821 $this->debug("parser debug: \n".$parser->getDebug()); 822 // if fault occurred during message parsing 823 if($err = $parser->getError()){ 824 $this->result = 'fault: error in msg parsing: '.$err; 825 $this->fault('SOAP-ENV:Client',"error in msg parsing:\n".$err); 826 // else successfully parsed request into soapval object 827 } else { 828 // get/set methodname 829 $this->methodURI = $parser->root_struct_namespace; 830 $this->methodname = $parser->root_struct_name; 831 $this->debug('methodname: '.$this->methodname.' methodURI: '.$this->methodURI); 832 $this->debug('calling parser->get_soapbody()'); 833 $this->methodparams = $parser->get_soapbody(); 834 // get SOAP headers 835 $this->requestHeaders = $parser->getHeaders(); 836 // get SOAP Header 837 $this->requestHeader = $parser->get_soapheader(); 838 // add document for doclit support 839 $this->document = $parser->document; 840 } 841 } 842 843 /** 844 * gets the HTTP body for the current response. 845 * 846 * @param string $soapmsg The SOAP payload 847 * @return string The HTTP body, which includes the SOAP payload 848 * @access private 849 */ 850 function getHTTPBody($soapmsg) { 851 return $soapmsg; 852 } 853 854 /** 855 * gets the HTTP content type for the current response. 856 * 857 * Note: getHTTPBody must be called before this. 858 * 859 * @return string the HTTP content type for the current response. 860 * @access private 861 */ 862 function getHTTPContentType() { 863 return 'text/xml'; 864 } 865 866 /** 867 * gets the HTTP content type charset for the current response. 868 * returns false for non-text content types. 869 * 870 * Note: getHTTPBody must be called before this. 871 * 872 * @return string the HTTP content type charset for the current response. 873 * @access private 874 */ 875 function getHTTPContentTypeCharset() { 876 return $this->soap_defencoding; 877 } 878 879 /** 880 * add a method to the dispatch map (this has been replaced by the register method) 881 * 882 * @param string $methodname 883 * @param string $in array of input values 884 * @param string $out array of output values 885 * @access public 886 * @deprecated 887 */ 888 function add_to_map($methodname,$in,$out){ 889 $this->operations[$methodname] = array('name' => $methodname,'in' => $in,'out' => $out); 890 } 891 892 /** 893 * register a service function with the server 894 * 895 * @param string $name the name of the PHP function, class.method or class..method 896 * @param array $in assoc array of input values: key = param name, value = param type 897 * @param array $out assoc array of output values: key = param name, value = param type 898 * @param mixed $namespace the element namespace for the method or false 899 * @param mixed $soapaction the soapaction for the method or false 900 * @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically 901 * @param mixed $use optional (encoded|literal) or false 902 * @param string $documentation optional Description to include in WSDL 903 * @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded) 904 * @access public 905 */ 906 function register($name,$in=array(),$out=array(),$namespace=false,$soapaction=false,$style=false,$use=false,$documentation='',$encodingStyle=''){ 907 global $HTTP_SERVER_VARS; 908 909 if($this->externalWSDLURL){ 910 die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.'); 911 } 912 if (! $name) { 913 die('You must specify a name when you register an operation'); 914 } 915 if (!is_array($in)) { 916 die('You must provide an array for operation inputs'); 917 } 918 if (!is_array($out)) { 919 die('You must provide an array for operation outputs'); 920 } 921 if(false == $namespace) { 922 } 923 if(false == $soapaction) { 924 if (isset($_SERVER)) { 925 $SERVER_NAME = $_SERVER['SERVER_NAME']; 926 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; 927 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); 928 } elseif (isset($HTTP_SERVER_VARS)) { 929 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; 930 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; 931 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; 932 } else { 933 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); 934 } 935 if ($HTTPS == '1' || $HTTPS == 'on') { 936 $SCHEME = 'https'; 937 } else { 938 $SCHEME = 'http'; 939 } 940 $soapaction = "$SCHEME://$SERVER_NAME$SCRIPT_NAME/$name"; 941 } 942 if(false == $style) { 943 $style = "rpc"; 944 } 945 if(false == $use) { 946 $use = "encoded"; 947 } 948 if ($use == 'encoded' && $encodingStyle = '') { 949 $encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/'; 950 } 951 952 $this->operations[$name] = array( 953 'name' => $name, 954 'in' => $in, 955 'out' => $out, 956 'namespace' => $namespace, 957 'soapaction' => $soapaction, 958 'style' => $style); 959 if($this->wsdl){ 960 $this->wsdl->addOperation($name,$in,$out,$namespace,$soapaction,$style,$use,$documentation,$encodingStyle); 961 } 962 return true; 963 } 964 965 /** 966 * Specify a fault to be returned to the client. 967 * This also acts as a flag to the server that a fault has occured. 968 * 969 * @param string $faultcode 970 * @param string $faultstring 971 * @param string $faultactor 972 * @param string $faultdetail 973 * @access public 974 */ 975 function fault($faultcode,$faultstring,$faultactor='',$faultdetail=''){ 976 if ($faultdetail == '' && $this->debug_flag) { 977 $faultdetail = $this->getDebug(); 978 } 979 $this->fault = new nusoap_fault($faultcode,$faultactor,$faultstring,$faultdetail); 980 $this->fault->soap_defencoding = $this->soap_defencoding; 981 } 982 983 /** 984 * Sets up wsdl object. 985 * Acts as a flag to enable internal WSDL generation 986 * 987 * @param string $serviceName, name of the service 988 * @param mixed $namespace optional 'tns' service namespace or false 989 * @param mixed $endpoint optional URL of service endpoint or false 990 * @param string $style optional (rpc|document) WSDL style (also specified by operation) 991 * @param string $transport optional SOAP transport 992 * @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false 993 */ 994 function configureWSDL($serviceName,$namespace = false,$endpoint = false,$style='rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) 995 { 996 global $HTTP_SERVER_VARS; 997 998 if (isset($_SERVER)) { 999 $SERVER_NAME = $_SERVER['SERVER_NAME']; 1000 $SERVER_PORT = $_SERVER['SERVER_PORT']; 1001 $SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME']; 1002 $HTTPS = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : (isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'); 1003 } elseif (isset($HTTP_SERVER_VARS)) { 1004 $SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME']; 1005 $SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT']; 1006 $SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME']; 1007 $HTTPS = isset($HTTP_SERVER_VARS['HTTPS']) ? $HTTP_SERVER_VARS['HTTPS'] : 'off'; 1008 } else { 1009 $this->setError("Neither _SERVER nor HTTP_SERVER_VARS is available"); 1010 } 1011 // If server name has port number attached then strip it (else port number gets duplicated in WSDL output) (occurred using lighttpd and FastCGI) 1012 $colon = strpos($SERVER_NAME,":"); 1013 if ($colon) { 1014 $SERVER_NAME = substr($SERVER_NAME, 0, $colon); 1015 } 1016 if ($SERVER_PORT == 80) { 1017 $SERVER_PORT = ''; 1018 } else { 1019 $SERVER_PORT = ':' . $SERVER_PORT; 1020 } 1021 if(false == $namespace) { 1022 $namespace = "http://$SERVER_NAME/soap/$serviceName"; 1023 } 1024 1025 if(false == $endpoint) { 1026 if ($HTTPS == '1' || $HTTPS == 'on') { 1027 $SCHEME = 'https'; 1028 } else { 1029 $SCHEME = 'http'; 1030 } 1031 $endpoint = "$SCHEME://$SERVER_NAME$SERVER_PORT$SCRIPT_NAME"; 1032 } 1033 1034 if(false == $schemaTargetNamespace) { 1035 $schemaTargetNamespace = $namespace; 1036 } 1037 1038 $this->wsdl = new wsdl; 1039 $this->wsdl->serviceName = $serviceName; 1040 $this->wsdl->endpoint = $endpoint; 1041 $this->wsdl->namespaces['tns'] = $namespace; 1042 $this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'; 1043 $this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'; 1044 if ($schemaTargetNamespace != $namespace) { 1045 $this->wsdl->namespaces['types'] = $schemaTargetNamespace; 1046 } 1047 $this->wsdl->schemas[$schemaTargetNamespace][0] = new nusoap_xmlschema('', '', $this->wsdl->namespaces); 1048 if ($style == 'document') { 1049 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaInfo['elementFormDefault'] = 'qualified'; 1050 } 1051 $this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace; 1052 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array('location' => '', 'loaded' => true); 1053 $this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array('location' => '', 'loaded' => true); 1054 $this->wsdl->bindings[$serviceName.'Binding'] = array( 1055 'name'=>$serviceName.'Binding', 1056 'style'=>$style, 1057 'transport'=>$transport, 1058 'portType'=>$serviceName.'PortType'); 1059 $this->wsdl->ports[$serviceName.'Port'] = array( 1060 'binding'=>$serviceName.'Binding', 1061 'location'=>$endpoint, 1062 'bindingType'=>'http://schemas.xmlsoap.org/wsdl/soap/'); 1063 } 1064 } 1065 1066 /** 1067 * Backward compatibility 1068 */ 1069 class soap_server extends nusoap_server { 1070 } 1071 1072 1073 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Thu Nov 29 09:42:17 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |