📄 class.soap_server.php
字号:
$this->request .= "$k: $v\r\n";
$this->debug("$k: $v");
}
} elseif (is_array($HTTP_SERVER_VARS)) {
$this->debug("In parse_http_headers, use HTTP_SERVER_VARS");
foreach ($HTTP_SERVER_VARS as $k => $v) {
if (substr($k, 0, 5) == 'HTTP_') {
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($k, 5)))); $k = strtolower(substr($k, 5));
} else {
$k = str_replace(' ', '-', strtolower(str_replace('_', ' ', $k))); $k = strtolower($k);
}
if ($k == 'soapaction') {
// get SOAPAction header
$k = 'SOAPAction';
$v = str_replace('"', '', $v);
$v = str_replace('\\', '', $v);
$this->SOAPAction = $v;
} else if ($k == 'content-type') {
// get the character encoding of the incoming request
if (strpos($v, '=')) {
$enc = substr(strstr($v, '='), 1);
$enc = str_replace('"', '', $enc);
$enc = str_replace('\\', '', $enc);
if (eregi('^(ISO-8859-1|US-ASCII|UTF-8)$', $enc)) {
$this->xml_encoding = strtoupper($enc);
} else {
$this->xml_encoding = 'US-ASCII';
}
} else {
// should be US-ASCII for HTTP 1.0 or ISO-8859-1 for HTTP 1.1
$this->xml_encoding = 'ISO-8859-1';
}
}
$this->headers[$k] = $v;
$this->request .= "$k: $v\r\n";
$this->debug("$k: $v");
}
} else {
$this->debug("In parse_http_headers, HTTP headers not accessible");
$this->setError("HTTP headers not accessible");
}
}
/**
* parses a request
*
* The following fields are set by this function (when successful)
*
* headers
* request
* xml_encoding
* SOAPAction
* request
* requestSOAP
* methodURI
* methodname
* methodparams
* requestHeaders
* document
*
* This sets the fault field on error
*
* @param string $data XML string
* @access private
*/
function parse_request($data='') {
$this->debug('entering parse_request()');
$this->parse_http_headers();
$this->debug('got character encoding: '.$this->xml_encoding);
// uncompress if necessary
if (isset($this->headers['content-encoding']) && $this->headers['content-encoding'] != '') {
$this->debug('got content encoding: ' . $this->headers['content-encoding']);
if ($this->headers['content-encoding'] == 'deflate' || $this->headers['content-encoding'] == 'gzip') {
// if decoding works, use it. else assume data wasn't gzencoded
if (function_exists('gzuncompress')) {
if ($this->headers['content-encoding'] == 'deflate' && $degzdata = @gzuncompress($data)) {
$data = $degzdata;
} elseif ($this->headers['content-encoding'] == 'gzip' && $degzdata = gzinflate(substr($data, 10))) {
$data = $degzdata;
} else {
$this->fault('SOAP-ENV:Client', 'Errors occurred when trying to decode the data');
return;
}
} else {
$this->fault('SOAP-ENV:Client', 'This Server does not support compressed data');
return;
}
}
}
$this->request .= "\r\n".$data;
$data = $this->parseRequest($this->headers, $data);
$this->requestSOAP = $data;
$this->debug('leaving parse_request');
}
/**
* invokes a PHP function for the requested SOAP method
*
* The following fields are set by this function (when successful)
*
* methodreturn
*
* Note that the PHP function that is called may also set the following
* fields to affect the response sent to the client
*
* responseHeaders
* outgoing_headers
*
* This sets the fault field on error
*
* @access private
*/
function invoke_method() {
$this->debug('in invoke_method, methodname=' . $this->methodname . ' methodURI=' . $this->methodURI . ' SOAPAction=' . $this->SOAPAction);
if ($this->wsdl) {
if ($this->opData = $this->wsdl->getOperationData($this->methodname)) {
$this->debug('in invoke_method, found WSDL operation=' . $this->methodname);
$this->appendDebug('opData=' . $this->varDump($this->opData));
} elseif ($this->opData = $this->wsdl->getOperationDataForSoapAction($this->SOAPAction)) {
// Note: hopefully this case will only be used for doc/lit, since rpc services should have wrapper element
$this->debug('in invoke_method, found WSDL soapAction=' . $this->SOAPAction . ' for operation=' . $this->opData['name']);
$this->appendDebug('opData=' . $this->varDump($this->opData));
$this->methodname = $this->opData['name'];
} else {
$this->debug('in invoke_method, no WSDL for operation=' . $this->methodname);
$this->fault('SOAP-ENV:Client', "Operation '" . $this->methodname . "' is not defined in the WSDL for this service");
return;
}
} else {
$this->debug('in invoke_method, no WSDL to validate method');
}
// if a . is present in $this->methodname, we see if there is a class in scope,
// which could be referred to. We will also distinguish between two deliminators,
// to allow methods to be called a the class or an instance
$class = '';
$method = '';
if (strpos($this->methodname, '..') > 0) {
$delim = '..';
} else if (strpos($this->methodname, '.') > 0) {
$delim = '.';
} else {
$delim = '';
}
if (strlen($delim) > 0 && substr_count($this->methodname, $delim) == 1 &&
class_exists(substr($this->methodname, 0, strpos($this->methodname, $delim)))) {
// get the class and method name
$class = substr($this->methodname, 0, strpos($this->methodname, $delim));
$method = substr($this->methodname, strpos($this->methodname, $delim) + strlen($delim));
$this->debug("in invoke_method, class=$class method=$method delim=$delim");
}
// does method exist?
if ($class == '') {
if (!function_exists($this->methodname)) {
$this->debug("in invoke_method, function '$this->methodname' not found!");
$this->result = 'fault: method not found';
$this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
return;
}
} else {
$method_to_compare = (substr(phpversion(), 0, 2) == '4.') ? strtolower($method) : $method;
if (!in_array($method_to_compare, get_class_methods($class))) {
$this->debug("in invoke_method, method '$this->methodname' not found in class '$class'!");
$this->result = 'fault: method not found';
$this->fault('SOAP-ENV:Client',"method '$this->methodname' not defined in service");
return;
}
}
// evaluate message, getting back parameters
// verify that request parameters match the method's signature
if(! $this->verify_method($this->methodname,$this->methodparams)){
// debug
$this->debug('ERROR: request not verified against method signature');
$this->result = 'fault: request failed validation against method signature';
// return fault
$this->fault('SOAP-ENV:Client',"Operation '$this->methodname' not defined in service.");
return;
}
// if there are parameters to pass
$this->debug('in invoke_method, params:');
$this->appendDebug($this->varDump($this->methodparams));
$this->debug("in invoke_method, calling '$this->methodname'");
if (!function_exists('call_user_func_array')) {
if ($class == '') {
$this->debug('in invoke_method, calling function using eval()');
$funcCall = "\$this->methodreturn = $this->methodname(";
} else {
if ($delim == '..') {
$this->debug('in invoke_method, calling class method using eval()');
$funcCall = "\$this->methodreturn = ".$class."::".$method."(";
} else {
$this->debug('in invoke_method, calling instance method using eval()');
// generate unique instance name
$instname = "\$inst_".time();
$funcCall = $instname." = new ".$class."(); ";
$funcCall .= "\$this->methodreturn = ".$instname."->".$method."(";
}
}
if ($this->methodparams) {
foreach ($this->methodparams as $param) {
if (is_array($param) || is_object($param)) {
$this->fault('SOAP-ENV:Client', 'NuSOAP does not handle complexType parameters correctly when using eval; call_user_func_array must be available');
return;
}
$funcCall .= "\"$param\",";
}
$funcCall = substr($funcCall, 0, -1);
}
$funcCall .= ');';
$this->debug('in invoke_method, function call: '.$funcCall);
@eval($funcCall);
} else {
if ($class == '') {
$this->debug('in invoke_method, calling function using call_user_func_array()');
$call_arg = "$this->methodname"; // straight assignment changes $this->methodname to lower case after call_user_func_array()
} elseif ($delim == '..') {
$this->debug('in invoke_method, calling class method using call_user_func_array()');
$call_arg = array ($class, $method);
} else {
$this->debug('in invoke_method, calling instance method using call_user_func_array()');
$instance = new $class ();
$call_arg = array(&$instance, $method);
}
if (is_array($this->methodparams)) {
$this->methodreturn = call_user_func_array($call_arg, array_values($this->methodparams));
} else {
$this->methodreturn = call_user_func_array($call_arg, array());
}
}
$this->debug('in invoke_method, methodreturn:');
$this->appendDebug($this->varDump($this->methodreturn));
$this->debug("in invoke_method, called method $this->methodname, received data of type ".gettype($this->methodreturn));
}
/**
* serializes the return value from a PHP function into a full SOAP Envelope
*
* The following fields are set by this function (when successful)
*
* responseSOAP
*
* This sets the fault field on error
*
* @access private
*/
function serialize_return() {
$this->debug('Entering serialize_return methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
// if fault
if (isset($this->methodreturn) && ((get_class($this->methodreturn) == 'soap_fault') || (get_class($this->methodreturn) == 'nusoap_fault'))) {
$this->debug('got a fault object from method');
$this->fault = $this->methodreturn;
return;
} elseif ($this->methodreturnisliteralxml) {
$return_val = $this->methodreturn;
// returned value(s)
} else {
$this->debug('got a(n) '.gettype($this->methodreturn).' from method');
$this->debug('serializing return value');
if($this->wsdl){
if (sizeof($this->opData['output']['parts']) > 1) {
$this->debug('more than one output part, so use the method return unchanged');
$opParams = $this->methodreturn;
} elseif (sizeof($this->opData['output']['parts']) == 1) {
$this->debug('exactly one output part, so wrap the method return in a simple array');
// TODO: verify that it is not already wrapped!
//foreach ($this->opData['output']['parts'] as $name => $type) {
// $this->debug('wrap in element named ' . $name);
//}
$opParams = array($this->methodreturn);
}
$return_val = $this->wsdl->serializeRPCParameters($this->methodname,'output',$opParams);
$this->appendDebug($this->wsdl->getDebug());
$this->wsdl->clearDebug();
if($errstr = $this->wsdl->getError()){
$this->debug('got wsdl error: '.$errstr);
$this->fault('SOAP-ENV:Server', 'unable to serialize result');
return;
}
} else {
if (isset($this->methodreturn)) {
$return_val = $this->serialize_val($this->methodreturn, 'return');
} else {
$return_val = '';
$this->debug('in absence of WSDL, assume void return for backward compatibility');
}
}
}
$this->debug('return value:');
$this->appendDebug($this->varDump($return_val));
$this->debug('serializing response');
if ($this->wsdl) {
$this->debug('have WSDL for serialization: style is ' . $this->opData['style']);
if ($this->opData['style'] == 'rpc') {
$this->debug('style is rpc for serialization: use is ' . $this->opData['output']['use']);
if ($this->opData['output']['use'] == 'literal') {
// 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
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
} else {
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
}
} else {
$this->debug('style is not rpc for serialization: assume document');
$payload = $return_val;
}
} else {
$this->debug('do not have WSDL for serialization: assume rpc/encoded');
$payload = '<ns1:'.$this->methodname.'Response xmlns:ns1="'.$this->methodURI.'">'.$return_val.'</ns1:'.$this->methodname."Response>";
}
$this->result = 'successful';
if($this->wsdl){
//if($this->debug_flag){
$this->appendDebug($this->wsdl->getDebug());
// }
if (isset($opData['output']['encodingStyle'])) {
$encodingStyle = $opData['output']['encodingStyle'];
} else {
$encodingStyle = '';
}
// Added: In case we use a WSDL, return a serialized env. WITH the usedNamespaces.
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders,$this->wsdl->usedNamespaces,$this->opData['style'],$this->opData['output']['use'],$encodingStyle);
} else {
$this->responseSOAP = $this->serializeEnvelope($payload,$this->responseHeaders);
}
$this->debug("Leaving serialize_return");
}
/**
* sends an HTTP response
*
* The following fields are set by this function (when successful)
*
* outgoing_headers
* response
*
* @access private
*/
function send_response() {
$this->debug('Enter send_response');
if ($this->fault) {
$payload = $this->fault->serialize();
$this->outgoing_headers[] = "HTTP/1.0 500 Internal Server Error";
$this->outgoing_headers[] = "Status: 500 Internal Server Error";
} else {
$payload = $this->responseSOAP;
// Some combinations of PHP+Web server allow the Status
// to come through as a header. Since OK is the default
// just do nothing.
// $this->outgoing_headers[] = "HTTP/1.0 200 OK";
// $this->outgoing_headers[] = "Status: 200 OK";
}
// add debug data if in debug mode
if(isset($this->debug_flag) && $this->debug_flag){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -