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