class soap_server in Salesforce Suite 5
Same name in this branch
- 5 includes/nusoap.php \soap_server
- 5 includes/nusoap.orig.php \soap_server
Same name and namespace in other branches
- 5.2 includes/nusoap.php \soap_server
- 5.2 includes/nusoap.orig.php \soap_server
soap_server allows the user to create a SOAP server that is capable of receiving messages and returning responses
NOTE: WSDL functionality is experimental
@author Dietrich Ayala <dietrich@ganx4.com> @access public
Hierarchy
- class \soap_server extends \nusoap_base
Expanded class hierarchy of soap_server
File
- includes/
nusoap.orig.php, line 3037
View source
class soap_server extends nusoap_base {
/**
* HTTP headers of request
* @var array
* @access private
*/
var $headers = [];
/**
* HTTP request
* @var string
* @access private
*/
var $request = '';
/**
* SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text)
* @var string
* @access public
*/
var $requestHeaders = '';
/**
* SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text)
* @var string
* @access public
*/
var $document = '';
/**
* SOAP payload for request (text)
* @var string
* @access public
*/
var $requestSOAP = '';
/**
* requested method namespace URI
* @var string
* @access private
*/
var $methodURI = '';
/**
* name of method requested
* @var string
* @access private
*/
var $methodname = '';
/**
* method parameters from request
* @var array
* @access private
*/
var $methodparams = [];
/**
* SOAP Action from request
* @var string
* @access private
*/
var $SOAPAction = '';
/**
* character set encoding of incoming (request) messages
* @var string
* @access public
*/
var $xml_encoding = '';
/**
* toggles whether the parser decodes element content w/ utf8_decode()
* @var boolean
* @access public
*/
var $decode_utf8 = true;
/**
* HTTP headers of response
* @var array
* @access public
*/
var $outgoing_headers = [];
/**
* HTTP response
* @var string
* @access private
*/
var $response = '';
/**
* SOAP headers for response (text)
* @var string
* @access public
*/
var $responseHeaders = '';
/**
* SOAP payload for response (text)
* @var string
* @access private
*/
var $responseSOAP = '';
/**
* method return value to place in response
* @var mixed
* @access private
*/
var $methodreturn = false;
/**
* whether $methodreturn is a string of literal XML
* @var boolean
* @access public
*/
var $methodreturnisliteralxml = false;
/**
* SOAP fault for response (or false)
* @var mixed
* @access private
*/
var $fault = false;
/**
* text indication of result (for debugging)
* @var string
* @access private
*/
var $result = 'successful';
/**
* assoc array of operations => opData; operations are added by the register()
* method or by parsing an external WSDL definition
* @var array
* @access private
*/
var $operations = [];
/**
* wsdl instance (if one)
* @var mixed
* @access private
*/
var $wsdl = false;
/**
* URL for WSDL (if one)
* @var mixed
* @access private
*/
var $externalWSDLURL = false;
/**
* whether to append debug to response as XML comment
* @var boolean
* @access public
*/
var $debug_flag = false;
/**
* constructor
* the optional parameter is a path to a WSDL file that you'd like to bind the server instance to.
*
* @param mixed $wsdl file path or URL (string), or wsdl instance (object)
* @access public
*/
function soap_server($wsdl = false) {
parent::nusoap_base();
// turn on debugging?
global $debug;
global $HTTP_SERVER_VARS;
if (isset($_SERVER)) {
$this
->debug("_SERVER is defined:");
$this
->appendDebug($this
->varDump($_SERVER));
}
elseif (isset($HTTP_SERVER_VARS)) {
$this
->debug("HTTP_SERVER_VARS is defined:");
$this
->appendDebug($this
->varDump($HTTP_SERVER_VARS));
}
else {
$this
->debug("Neither _SERVER nor HTTP_SERVER_VARS is defined.");
}
if (isset($debug)) {
$this
->debug("In soap_server, set debug_flag={$debug} based on global flag");
$this->debug_flag = $debug;
}
elseif (isset($_SERVER['QUERY_STRING'])) {
$qs = explode('&', $_SERVER['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this
->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #1");
$this->debug_flag = substr($v, 6);
}
}
}
elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
$qs = explode('&', $HTTP_SERVER_VARS['QUERY_STRING']);
foreach ($qs as $v) {
if (substr($v, 0, 6) == 'debug=') {
$this
->debug("In soap_server, set debug_flag=" . substr($v, 6) . " based on query string #2");
$this->debug_flag = substr($v, 6);
}
}
}
// wsdl
if ($wsdl) {
$this
->debug("In soap_server, WSDL is specified");
if (is_object($wsdl) && get_class($wsdl) == 'wsdl') {
$this->wsdl = $wsdl;
$this->externalWSDLURL = $this->wsdl->wsdl;
$this
->debug('Use existing wsdl instance from ' . $this->externalWSDLURL);
}
else {
$this
->debug('Create wsdl from ' . $wsdl);
$this->wsdl = new wsdl($wsdl);
$this->externalWSDLURL = $wsdl;
}
$this
->appendDebug($this->wsdl
->getDebug());
$this->wsdl
->clearDebug();
if ($err = $this->wsdl
->getError()) {
die('WSDL ERROR: ' . $err);
}
}
}
/**
* processes request and returns response
*
* @param string $data usually is the value of $HTTP_RAW_POST_DATA
* @access public
*/
function service($data) {
global $HTTP_SERVER_VARS;
if (isset($_SERVER['QUERY_STRING'])) {
$qs = $_SERVER['QUERY_STRING'];
}
elseif (isset($HTTP_SERVER_VARS['QUERY_STRING'])) {
$qs = $HTTP_SERVER_VARS['QUERY_STRING'];
}
else {
$qs = '';
}
$this
->debug("In service, query string={$qs}");
if (ereg('wsdl', $qs)) {
$this
->debug("In service, this is a request for WSDL");
if ($this->externalWSDLURL) {
if (strpos($this->externalWSDLURL, "://") !== false) {
// assume URL
header('Location: ' . $this->externalWSDLURL);
}
else {
// assume file
header("Content-Type: text/xml\r\n");
$fp = fopen($this->externalWSDLURL, 'r');
fpassthru($fp);
}
}
elseif ($this->wsdl) {
header("Content-Type: text/xml; charset=ISO-8859-1\r\n");
print $this->wsdl
->serialize($this->debug_flag);
if ($this->debug_flag) {
$this
->debug('wsdl:');
$this
->appendDebug($this
->varDump($this->wsdl));
print $this
->getDebugAsXMLComment();
}
}
else {
header("Content-Type: text/html; charset=ISO-8859-1\r\n");
print "This service does not provide WSDL";
}
}
elseif ($data == '' && $this->wsdl) {
$this
->debug("In service, there is no data, so return Web description");
print $this->wsdl
->webDescription();
}
else {
$this
->debug("In service, invoke the request");
$this
->parse_request($data);
if (!$this->fault) {
$this
->invoke_method();
}
if (!$this->fault) {
$this
->serialize_return();
}
$this
->send_response();
}
}
/**
* parses HTTP request headers.
*
* The following fields are set by this function (when successful)
*
* headers
* request
* xml_encoding
* SOAPAction
*
* @access private
*/
function parse_http_headers() {
global $HTTP_SERVER_VARS;
$this->request = '';
$this->SOAPAction = '';
if (function_exists('getallheaders')) {
$this
->debug("In parse_http_headers, use getallheaders");
$headers = getallheaders();
foreach ($headers as $k => $v) {
$k = strtolower($k);
$this->headers[$k] = $v;
$this->request .= "{$k}: {$v}\r\n";
$this
->debug("{$k}: {$v}");
}
// get SOAPAction header
if (isset($this->headers['soapaction'])) {
$this->SOAPAction = str_replace('"', '', $this->headers['soapaction']);
}
// get the character encoding of the incoming request
if (isset($this->headers['content-type']) && strpos($this->headers['content-type'], '=')) {
$enc = str_replace('"', '', substr(strstr($this->headers["content-type"], '='), 1));
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';
}
}
elseif (isset($_SERVER) && is_array($_SERVER)) {
$this
->debug("In parse_http_headers, use _SERVER");
foreach ($_SERVER 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}");
}
}
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('Client', 'Errors occurred when trying to decode the data');
return;
}
}
else {
$this
->fault('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('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('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('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('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)) {
$this
->fault('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,
);
}
$this->methodreturn = call_user_func_array($call_arg, $this->methodparams);
}
$this
->debug('in invoke_method, methodreturn:');
$this
->appendDebug($this
->varDump($this->methodreturn));
$this
->debug("in invoke_method, called method {$this->methodname}, received {$this->methodreturn} 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') {
$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) {
// weak attempt at supporting multiple output params
if (sizeof($this->opData['output']['parts']) > 1) {
$opParams = $this->methodreturn;
}
else {
// TODO: is this really necessary?
$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('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') {
$payload = '<' . $this->methodname . 'Response xmlns="' . $this->methodURI . '">' . $return_val . '</' . $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'], $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) {
$payload .= $this
->getDebugAsXMLComment();
}
$this->outgoing_headers[] = "Server: {$this->title} Server v{$this->version}";
ereg('\\$Revisio' . 'n: ([^ ]+)', $this->revision, $rev);
$this->outgoing_headers[] = "X-SOAP-Server: {$this->title}/{$this->version} (" . $rev[1] . ")";
// Let the Web server decide about this
//$this->outgoing_headers[] = "Connection: Close\r\n";
$payload = $this
->getHTTPBody($payload);
$type = $this
->getHTTPContentType();
$charset = $this
->getHTTPContentTypeCharset();
$this->outgoing_headers[] = "Content-Type: {$type}" . ($charset ? '; charset=' . $charset : '');
//begin code to compress payload - by John
// NOTE: there is no way to know whether the Web server will also compress
// this data.
if (strlen($payload) > 1024 && isset($this->headers) && isset($this->headers['accept-encoding'])) {
if (strstr($this->headers['accept-encoding'], 'gzip')) {
if (function_exists('gzencode')) {
if (isset($this->debug_flag) && $this->debug_flag) {
$payload .= "<!-- Content being gzipped -->";
}
$this->outgoing_headers[] = "Content-Encoding: gzip";
$payload = gzencode($payload);
}
else {
if (isset($this->debug_flag) && $this->debug_flag) {
$payload .= "<!-- Content will not be gzipped: no gzencode -->";
}
}
}
elseif (strstr($this->headers['accept-encoding'], 'deflate')) {
// Note: MSIE requires gzdeflate output (no Zlib header and checksum),
// instead of gzcompress output,
// which conflicts with HTTP 1.1 spec (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.5)
if (function_exists('gzdeflate')) {
if (isset($this->debug_flag) && $this->debug_flag) {
$payload .= "<!-- Content being deflated -->";
}
$this->outgoing_headers[] = "Content-Encoding: deflate";
$payload = gzdeflate($payload);
}
else {
if (isset($this->debug_flag) && $this->debug_flag) {
$payload .= "<!-- Content will not be deflated: no gzcompress -->";
}
}
}
}
//end code
$this->outgoing_headers[] = "Content-Length: " . strlen($payload);
reset($this->outgoing_headers);
foreach ($this->outgoing_headers as $hdr) {
header($hdr, false);
}
print $payload;
$this->response = join("\r\n", $this->outgoing_headers) . "\r\n\r\n" . $payload;
}
/**
* takes the value that was created by parsing the request
* and compares to the method's signature, if available.
*
* @param string $operation The operation to be invoked
* @param array $request The array of parameter values
* @return boolean Whether the operation was found
* @access private
*/
function verify_method($operation, $request) {
if (isset($this->wsdl) && is_object($this->wsdl)) {
if ($this->wsdl
->getOperationData($operation)) {
return true;
}
}
elseif (isset($this->operations[$operation])) {
return true;
}
return false;
}
/**
* processes SOAP message received from client
*
* @param array $headers The HTTP headers
* @param string $data unprocessed request data from client
* @return mixed value of the message, decoded into a PHP type
* @access private
*/
function parseRequest($headers, $data) {
$this
->debug('Entering parseRequest() for data of length ' . strlen($data) . ' and type ' . $headers['content-type']);
if (!strstr($headers['content-type'], 'text/xml')) {
$this
->setError('Request not of type text/xml');
return false;
}
if (strpos($headers['content-type'], '=')) {
$enc = str_replace('"', '', substr(strstr($headers["content-type"], '='), 1));
$this
->debug('Got response encoding: ' . $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
->debug('Use encoding: ' . $this->xml_encoding . ' when creating soap_parser');
// parse response, get soap parser obj
$parser = new soap_parser($data, $this->xml_encoding, '', $this->decode_utf8);
// parser debug
$this
->debug("parser debug: \n" . $parser
->getDebug());
// if fault occurred during message parsing
if ($err = $parser
->getError()) {
$this->result = 'fault: error in msg parsing: ' . $err;
$this
->fault('Client', "error in msg parsing:\n" . $err);
// else successfully parsed request into soapval object
}
else {
// get/set methodname
$this->methodURI = $parser->root_struct_namespace;
$this->methodname = $parser->root_struct_name;
$this
->debug('methodname: ' . $this->methodname . ' methodURI: ' . $this->methodURI);
$this
->debug('calling parser->get_response()');
$this->methodparams = $parser
->get_response();
// get SOAP headers
$this->requestHeaders = $parser
->getHeaders();
// add document for doclit support
$this->document = $parser->document;
}
}
/**
* gets the HTTP body for the current response.
*
* @param string $soapmsg The SOAP payload
* @return string The HTTP body, which includes the SOAP payload
* @access private
*/
function getHTTPBody($soapmsg) {
return $soapmsg;
}
/**
* gets the HTTP content type for the current response.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type for the current response.
* @access private
*/
function getHTTPContentType() {
return 'text/xml';
}
/**
* gets the HTTP content type charset for the current response.
* returns false for non-text content types.
*
* Note: getHTTPBody must be called before this.
*
* @return string the HTTP content type charset for the current response.
* @access private
*/
function getHTTPContentTypeCharset() {
return $this->soap_defencoding;
}
/**
* add a method to the dispatch map (this has been replaced by the register method)
*
* @param string $methodname
* @param string $in array of input values
* @param string $out array of output values
* @access public
* @deprecated
*/
function add_to_map($methodname, $in, $out) {
$this->operations[$methodname] = array(
'name' => $methodname,
'in' => $in,
'out' => $out,
);
}
/**
* register a service function with the server
*
* @param string $name the name of the PHP function, class.method or class..method
* @param array $in assoc array of input values: key = param name, value = param type
* @param array $out assoc array of output values: key = param name, value = param type
* @param mixed $namespace the element namespace for the method or false
* @param mixed $soapaction the soapaction for the method or false
* @param mixed $style optional (rpc|document) or false Note: when 'document' is specified, parameter and return wrappers are created for you automatically
* @param mixed $use optional (encoded|literal) or false
* @param string $documentation optional Description to include in WSDL
* @param string $encodingStyle optional (usually 'http://schemas.xmlsoap.org/soap/encoding/' for encoded)
* @access public
*/
function register($name, $in = [], $out = [], $namespace = false, $soapaction = false, $style = false, $use = false, $documentation = '', $encodingStyle = '') {
global $HTTP_SERVER_VARS;
if ($this->externalWSDLURL) {
die('You cannot bind to an external WSDL file, and register methods outside of it! Please choose either WSDL or no WSDL.');
}
if (!$name) {
die('You must specify a name when you register an operation');
}
if (!is_array($in)) {
die('You must provide an array for operation inputs');
}
if (!is_array($out)) {
die('You must provide an array for operation outputs');
}
if (false == $namespace) {
}
if (false == $soapaction) {
if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
}
elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
}
else {
$this
->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
}
$soapaction = "http://{$SERVER_NAME}{$SCRIPT_NAME}/{$name}";
}
if (false == $style) {
$style = "rpc";
}
if (false == $use) {
$use = "encoded";
}
if ($use == 'encoded' && ($encodingStyle = '')) {
$encodingStyle = 'http://schemas.xmlsoap.org/soap/encoding/';
}
$this->operations[$name] = array(
'name' => $name,
'in' => $in,
'out' => $out,
'namespace' => $namespace,
'soapaction' => $soapaction,
'style' => $style,
);
if ($this->wsdl) {
$this->wsdl
->addOperation($name, $in, $out, $namespace, $soapaction, $style, $use, $documentation, $encodingStyle);
}
return true;
}
/**
* Specify a fault to be returned to the client.
* This also acts as a flag to the server that a fault has occured.
*
* @param string $faultcode
* @param string $faultstring
* @param string $faultactor
* @param string $faultdetail
* @access public
*/
function fault($faultcode, $faultstring, $faultactor = '', $faultdetail = '') {
if ($faultdetail == '' && $this->debug_flag) {
$faultdetail = $this
->getDebug();
}
$this->fault = new soap_fault($faultcode, $faultactor, $faultstring, $faultdetail);
$this->fault->soap_defencoding = $this->soap_defencoding;
}
/**
* Sets up wsdl object.
* Acts as a flag to enable internal WSDL generation
*
* @param string $serviceName, name of the service
* @param mixed $namespace optional 'tns' service namespace or false
* @param mixed $endpoint optional URL of service endpoint or false
* @param string $style optional (rpc|document) WSDL style (also specified by operation)
* @param string $transport optional SOAP transport
* @param mixed $schemaTargetNamespace optional 'types' targetNamespace for service schema or false
*/
function configureWSDL($serviceName, $namespace = false, $endpoint = false, $style = 'rpc', $transport = 'http://schemas.xmlsoap.org/soap/http', $schemaTargetNamespace = false) {
global $HTTP_SERVER_VARS;
if (isset($_SERVER)) {
$SERVER_NAME = $_SERVER['SERVER_NAME'];
$SERVER_PORT = $_SERVER['SERVER_PORT'];
$SCRIPT_NAME = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$HTTPS = $_SERVER['HTTPS'];
}
elseif (isset($HTTP_SERVER_VARS)) {
$SERVER_NAME = $HTTP_SERVER_VARS['SERVER_NAME'];
$SERVER_PORT = $HTTP_SERVER_VARS['SERVER_PORT'];
$SCRIPT_NAME = isset($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : $HTTP_SERVER_VARS['SCRIPT_NAME'];
$HTTPS = $HTTP_SERVER_VARS['HTTPS'];
}
else {
$this
->setError("Neither _SERVER nor HTTP_SERVER_VARS is available");
}
if ($SERVER_PORT == 80) {
$SERVER_PORT = '';
}
else {
$SERVER_PORT = ':' . $SERVER_PORT;
}
if (false == $namespace) {
$namespace = "http://{$SERVER_NAME}/soap/{$serviceName}";
}
if (false == $endpoint) {
if ($HTTPS == '1' || $HTTPS == 'on') {
$SCHEME = 'https';
}
else {
$SCHEME = 'http';
}
$endpoint = "{$SCHEME}://{$SERVER_NAME}{$SERVER_PORT}{$SCRIPT_NAME}";
}
if (false == $schemaTargetNamespace) {
$schemaTargetNamespace = $namespace;
}
$this->wsdl = new wsdl();
$this->wsdl->serviceName = $serviceName;
$this->wsdl->endpoint = $endpoint;
$this->wsdl->namespaces['tns'] = $namespace;
$this->wsdl->namespaces['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/';
$this->wsdl->namespaces['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/';
if ($schemaTargetNamespace != $namespace) {
$this->wsdl->namespaces['types'] = $schemaTargetNamespace;
}
$this->wsdl->schemas[$schemaTargetNamespace][0] = new xmlschema('', '', $this->wsdl->namespaces);
$this->wsdl->schemas[$schemaTargetNamespace][0]->schemaTargetNamespace = $schemaTargetNamespace;
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/soap/encoding/'][0] = array(
'location' => '',
'loaded' => true,
);
$this->wsdl->schemas[$schemaTargetNamespace][0]->imports['http://schemas.xmlsoap.org/wsdl/'][0] = array(
'location' => '',
'loaded' => true,
);
$this->wsdl->bindings[$serviceName . 'Binding'] = array(
'name' => $serviceName . 'Binding',
'style' => $style,
'transport' => $transport,
'portType' => $serviceName . 'PortType',
);
$this->wsdl->ports[$serviceName . 'Port'] = array(
'binding' => $serviceName . 'Binding',
'location' => $endpoint,
'bindingType' => 'http://schemas.xmlsoap.org/wsdl/soap/',
);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
soap_server:: |
property | * whether to append debug to response as XML comment * * @access public | ||
soap_server:: |
property | * toggles whether the parser decodes element content w/ utf8_decode() * * @access public | ||
soap_server:: |
property | * SOAP body request portion (incomplete namespace resolution; special characters not escaped) (text) * * @access public | ||
soap_server:: |
property | * URL for WSDL (if one) * * @access private | ||
soap_server:: |
property | * SOAP fault for response (or false) * * @access private | ||
soap_server:: |
property | * HTTP headers of request * * @access private | ||
soap_server:: |
property | * name of method requested * * @access private | ||
soap_server:: |
property | * method parameters from request * * @access private | ||
soap_server:: |
property | * method return value to place in response * * @access private | ||
soap_server:: |
property | * whether $methodreturn is a string of literal XML * * @access public | ||
soap_server:: |
property | * requested method namespace URI * * @access private | ||
soap_server:: |
property | * assoc array of operations => opData; operations are added by the register() * method or by parsing an external WSDL definition * * @access private | ||
soap_server:: |
property | * HTTP headers of response * * @access public | ||
soap_server:: |
property | * HTTP request * * @access private | ||
soap_server:: |
property | * SOAP headers from request (incomplete namespace resolution; special characters not escaped) (text) * * @access public | ||
soap_server:: |
property | * SOAP payload for request (text) * * @access public | ||
soap_server:: |
property | * HTTP response * * @access private | ||
soap_server:: |
property | * SOAP headers for response (text) * * @access public | ||
soap_server:: |
property | * SOAP payload for response (text) * * @access private | ||
soap_server:: |
property | * text indication of result (for debugging) * * @access private | ||
soap_server:: |
property | * SOAP Action from request * * @access private | ||
soap_server:: |
property | * wsdl instance (if one) * * @access private | ||
soap_server:: |
property | * character set encoding of incoming (request) messages * * @access public | ||
soap_server:: |
function | * add a method to the dispatch map (this has been replaced by the register method) * * | ||
soap_server:: |
function | Sets up wsdl object. Acts as a flag to enable internal WSDL generation | ||
soap_server:: |
function | * Specify a fault to be returned to the client. * This also acts as a flag to the server that a fault has occured. * * | ||
soap_server:: |
function | * gets the HTTP body for the current response. * * | ||
soap_server:: |
function | * gets the HTTP content type for the current response. * * Note: getHTTPBody must be called before this. * * | ||
soap_server:: |
function | * gets the HTTP content type charset for the current response. * returns false for non-text content types. * * Note: getHTTPBody must be called before this. * * | ||
soap_server:: |
function | * 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… | ||
soap_server:: |
function | * processes SOAP message received from client * * | ||
soap_server:: |
function | * parses HTTP request headers. * * The following fields are set by this function (when successful) * * headers * request * xml_encoding * SOAPAction * * @access private | ||
soap_server:: |
function | * 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 * *… | ||
soap_server:: |
function | * register a service function with the server * * | ||
soap_server:: |
function | * sends an HTTP response * * The following fields are set by this function (when successful) * * outgoing_headers * response * * @access private | ||
soap_server:: |
function | * 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 | ||
soap_server:: |
function | * processes request and returns response * * | ||
soap_server:: |
function | * constructor the optional parameter is a path to a WSDL file that you'd like to bind the server instance to. * | ||
soap_server:: |
function | * takes the value that was created by parsing the request * and compares to the method's signature, if available. * * |