📄 server.php.svn-base
字号:
<?php/** * This file contains the code for the SOAP server. * * PHP versions 4 and 5 * * LICENSE: This source file is subject to version 2.02 of the PHP license, * that is bundled with this package in the file LICENSE, and is available at * through the world-wide-web at http://www.php.net/license/2_02.txt. If you * did not receive a copy of the PHP license and are unable to obtain it * through the world-wide-web, please send a note to license@php.net so we can * mail you a copy immediately. * * @category Web Services * @package SOAP * @author Dietrich Ayala <dietrich@ganx4.com> Original Author * @author Shane Caraveo <Shane@Caraveo.com> Port to PEAR and more * @author Chuck Hagenbuch <chuck@horde.org> Maintenance * @author Jan Schneider <jan@horde.org> Maintenance * @copyright 2003-2005 The PHP Group * @license http://www.php.net/license/2_02.txt PHP License 2.02 * @link http://pear.php.net/package/SOAP */require_once 'SOAP/Base.php';require_once 'SOAP/Fault.php';require_once 'SOAP/Parser.php';require_once 'SOAP/Value.php';require_once 'SOAP/WSDL.php';/** * SOAP Server Class * * Originaly based on SOAPx4 by Dietrich Ayala * http://dietrich.ganx4.com/soapx4 * * @access public * @package SOAP * @author Shane Caraveo <shane@php.net> Conversion to PEAR and updates * @author Dietrich Ayala <dietrich@ganx4.com> Original Author */class SOAP_Server extends SOAP_Base{ /** * * @var array */ var $dispatch_map = array(); // create empty dispatch map var $dispatch_objects = array(); var $soapobject = null; var $call_methodname = null; var $callHandler = null; var $callValidation = true; /** * A list of headers that are going to be sent back to the client. * * @var array */ var $headers = array(); /** * * @var string */ var $request = ''; /** * * @var string XML-Encoding */ var $xml_encoding = SOAP_DEFAULT_ENCODING; var $response_encoding = 'UTF-8'; var $result = 'successful'; // for logging interop results to db var $endpoint = ''; // the uri to ME! var $service = ''; //soapaction header var $method_namespace = null; var $__options = array('use' => 'encoded', 'style' => 'rpc', 'parameters' => 0, 'http_status_success' => '200 OK', 'http_status_fault' => '500 SOAP Fault'); function SOAP_Server($options = null) { ini_set('track_errors', 1); parent::SOAP_Base('Server'); if (is_array($options)) { if (isset($options['use'])) { $this->__options['use'] = $options['use']; } if (isset($options['style'])) { $this->__options['style'] = $options['style']; } if (isset($options['parameters'])) { $this->__options['parameters'] = $options['parameters']; } } // assume we encode with section 5 $this->_section5 = true; if ($this->__options['use']=='literal') { $this->_section5 = false; } } /** * Error handler for errors that happen in proxied methods. * * To always return a valid SOAP response even on errors that don't happen * in this code, the errors are catched, transformed to a SOAP fault and * immediately sent to the client. * * @see http://www.php.net/set_error_handler */ function _errorHandler($errno, $errmsg, $filename, $linenum, $vars) { /* The error handler should ignore '0' errors, eg. hidden by @ - see * the set_error_handler manual page. (thanks to Alan Knowles). */ if (!$errno || $errno == E_NOTICE || (defined('E_STRICT') && $errno == constant('E_STRICT'))) { return; } $this->fault =& new SOAP_Fault($errmsg, 'Server', 'PHP', "Errno: $errno\nFilename: $filename\nLineno: $linenum\n"); $this->_sendResponse(); exit; } function _getContentEncoding($content_type) { /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ $this->xml_encoding = 'UTF-8'; if (strpos($content_type, '=')) { $enc = strtoupper(str_replace('"', '', substr(strstr($content_type, '='), 1))); if (!in_array($enc, $this->_encodings)) { return false; } $this->xml_encoding = $enc; } return true; } /** * Parses request and posts response. */ function service($data, $endpoint = '', $test = false) { $response = null; $attachments = array(); $useEncoding = 'DIME'; /* Figure out our endpoint. */ $this->endpoint = $endpoint; if (!$test && !$this->endpoint) { /* We'll try to build our endpoint. */ $this->endpoint = 'http://' . $_SERVER['SERVER_NAME']; if ($_SERVER['SERVER_PORT']) { $this->endpoint .= ':' . $_SERVER['SERVER_PORT']; } $this->endpoint .= $_SERVER['SCRIPT_NAME']; } /* Get the character encoding of the incoming request treat incoming * data as UTF-8 if no encoding set. */ if (isset($_SERVER['CONTENT_TYPE'])) { if (strcasecmp($_SERVER['CONTENT_TYPE'], 'application/dime') == 0) { $this->_decodeDIMEMessage($data, $headers, $attachments); $useEncoding = 'DIME'; } elseif (stristr($_SERVER['CONTENT_TYPE'], 'multipart/related')) { /* This is a mime message, let's decode it. */ $data = 'Content-Type: ' . stripslashes($_SERVER['CONTENT_TYPE']) . "\r\n\r\n" . $data; $this->_decodeMimeMessage($data, $headers, $attachments); $useEncoding = 'Mime'; } if (!isset($headers['content-type'])) { $headers['content-type'] = stripslashes($_SERVER['CONTENT_TYPE']); } if (!$this->fault && !$this->_getContentEncoding($headers['content-type'])) { $this->xml_encoding = SOAP_DEFAULT_ENCODING; /* Found encoding we don't understand; return a fault. */ $this->_raiseSoapFault('Unsupported encoding, use one of ISO-8859-1, US-ASCII, UTF-8', '', '', 'Server'); } } /* If this is not a POST with Content-Type text/xml, try to return a * WSDL file. */ if (!$this->fault && !$test && ($_SERVER['REQUEST_METHOD'] != 'POST' || strncmp($headers['content-type'], 'text/xml', 8) != 0)) { /* This is not possibly a valid SOAP request, try to return a WSDL * file. */ $this->_raiseSoapFault('Invalid SOAP request, must be POST with content-type: text/xml, got: ' . (isset($headers['content-type']) ? $headers['content-type'] : 'Nothing!'), '', '', 'Server'); } if (!$this->fault) { /* $response is a SOAP_Msg object. */ $soap_msg = $this->parseRequest($data, $attachments); /* Handle Mime or DIME encoding. */ /* TODO: DIME decoding should move to the transport, do it here * for now and for ease of getting it done. */ if (count($this->__attachments)) { if ($useEncoding == 'Mime') { $soap_msg = $this->_makeMimeMessage($soap_msg); } else { // default is dime $soap_msg = $this->_makeDIMEMessage($soap_msg); $this->headers['Content-Type'] = 'application/dime'; } if (PEAR::isError($soap_msg)) { return $this->_raiseSoapFault($soap_msg); } } if (is_array($soap_msg)) { $response = $soap_msg['body']; if (count($soap_msg['headers'])) { $this->headers = $soap_msg['headers']; } } else { $response = $soap_msg; } } $this->_sendResponse($response); } /** * Sends the final HTTP response to the client, including the HTTP header * and the HTTP body. * * If an error happened, it returns a SOAP fault instead of the response * body. * * @param string $response The response body. */ function _sendResponse($response = '') { /* Make distinction between the different SAPIs, running PHP as CGI or * as a module. */ if (stristr(php_sapi_name(), 'cgi') === 0) { $hdrs_type = 'Status:'; } else { $hdrs_type = 'HTTP/1.1'; } if ($this->fault) { $hdrs = $hdrs_type . ' ' . $this->__options['http_status_fault'] . "\r\n"; $response = $this->fault->message(); } else { $hdrs = $hdrs_type . ' ' . $this->__options['http_status_success'] . "\r\n"; } header($hdrs); $this->headers['Server'] = SOAP_LIBRARY_NAME; if (!isset($this->headers['Content-Type'])) { $this->headers['Content-Type'] = 'text/xml; charset=' . $this->response_encoding; } $this->headers['Content-Length'] = strlen($response); foreach ($this->headers as $k => $v) { header("$k: $v"); $hdrs .= "$k: $v\r\n"; } $this->response = $hdrs . "\r\n" . $response; print $response; } function &callMethod($methodname, &$args) { if ($this->callHandler) { $ret = @call_user_func_array($this->callHandler, array($methodname, $args)); return $ret; } set_error_handler(array($this, '_errorHandler')); if ($args) { /* Call method with parameters. */ if (isset($this->soapobject) && is_object($this->soapobject)) { $ret = @call_user_func_array(array(&$this->soapobject, $methodname), $args); } else { $ret = @call_user_func_array($methodname, $args); } } else { /* Call method withour parameters. */ if (is_object($this->soapobject)) { $ret = @call_user_func(array(&$this->soapobject, $methodname)); } else { $ret = @call_user_func($methodname); } } restore_error_handler(); return $ret; } /** * Creates SOAP_Value objects with return values from method. * Uses method signature to determine type. * * @param mixed $method_response The result(s). * @param array|string $type The type(s) of the return value(s). * @param string $return_name The name of the return value. * @param string $namespace The namespace of the return value. * * @return array List of SOAP_Value objects. */ function buildResult(&$method_response, &$return_type, $return_name = 'return', $namespace = '') { if (is_a($method_response, 'SOAP_Value')) { $return_val = array($method_response); } else { if (is_array($return_type) && is_array($method_response)) { $i = 0; foreach ($return_type as $key => $type) { if (is_numeric($key)) { $key = 'item'; } if (is_a($method_response[$i], 'SOAP_Value')) { $return_val[] =& $method_response[$i++]; } else { $qn =& new QName($key, $namespace); $return_val[] =& new SOAP_Value($qn->fqn(), $type, $method_response[$i++]); } } } else { if (is_array($return_type)) { $keys = array_keys($return_type); if (!is_numeric($keys[0])) { $return_name = $keys[0]; } $values = array_values($return_type); $return_type = $values[0]; } $qn =& new QName($return_name, $namespace); $return_val = array(new SOAP_Value($qn->fqn(), $return_type, $method_response)); } } return $return_val; } function parseRequest($data = '', $attachments = null) { /* Parse response, get SOAP_Parser object. */ $parser =& new SOAP_Parser($data, $this->xml_encoding, $attachments); /* If fault occurred during message parsing. */ if ($parser->fault) { $this->fault = $parser->fault; return null; } /* Handle message headers. */ $request_headers = $parser->getHeaders(); $header_results = array(); if ($request_headers) { if (!is_a($request_headers, 'SOAP_Value')) { $this->_raiseSoapFault('Parser did not return SOAP_Value object: ' . $request_headers, '', '', 'Server'); return null; } if ($request_headers->value) { /* Handle headers now. */ foreach ($request_headers->value as $header_val) { $f_exists = $this->validateMethod($header_val->name, $header_val->namespace); /* TODO: this does not take into account message routing * yet. */ $myactor = !$header_val->actor || $header_val->actor == 'http://schemas.xmlsoap.org/soap/actor/next' || $header_val->actor == $this->endpoint; if (!$f_exists && $header_val->mustunderstand && $myactor) { $this->_raiseSoapFault('I don\'t understand header ' . $header_val->name, '', '', 'MustUnderstand'); return null; } /* We only handle the header if it's for us. */ $isok = $f_exists && $myactor; if ($isok) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -