Source for file NS_SOAP_Service_Handler.php
Documentation is available at NS_SOAP_Service_Handler.php
* nanoserv handlers - SOAP 1.1 over HTTP service handler
* Copyright (C) 2004-2010 Vincent Negrier aka. sIX <six@aegis-corp.org>
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
* Require the HTTP server
require_once "nanoserv-compat/handlers/NS_HTTP_Service_Handler.php";
* SOAP 1.1 over HTTP Service handler class
* Last called method name
* List of exported methods with their parameters
* Defines the host name of the server, useful for WSDL automatic generation
* NS_SOAP_Service_Handler constructor
* The constructor here only builds the exports list for WSDL automatic generation
if (isset ($options["hostname"])) {
* Get list of exported methods with their parameters
* This methods needs to be overloaded and return the correct list in child classes
* Convert a PHP variable to SOAP string representation
foreach ($var as $k => $v) {
if (is_numeric($k) && ($key !== false)) $k = $key . "_member";
* Add SOAP response envelope
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><SOAP-ENV:Body>{$result}</SOAP-ENV:Body></SOAP-ENV:Envelope>";
* Returns a correctly formatted SOAP fault result
protected function Fault($string, $code= "Server") {
return $this->SOAP_Add_Response_Envelope("<SOAP-ENV:Fault><faultcode>SOAP-ENV:{$code}</faultcode><faultstring>{$string}</faultstring></SOAP-ENV:Fault>");
* Returns a base location for the HTTP service based on the hostname option and the listening port
if (substr($sn = $this->socket->Get_Name(), - 3) !== ":80") {
if (substr($sn = $this->socket->Get_Name(), - 3) !== ":80") {
* Generates a WSDL document for the current service
$ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$ret .= "<definitions targetNamespace=\"urn:nssoap.{$classname}\"\n";
$ret .= " xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n";
$ret .= " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
$ret .= " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n";
$ret .= " xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"\n";
$ret .= " xmlns:xsd". (++ $i). "=\"urn:nssoap.{$mname}_d\"\n";
$ret .= "<import namespace=\"urn:nssoap.{$mname}_d\" location=\"{$base_href}/{$mname}/xsd\" />\n\n";
$ret .= "<message name=\"{$mname}\">\n";
$ret .= " <part name=\"{$mname}\" element=\"xsd". (++ $i). ":{$mname}\" />\n";
$ret .= "</message>\n\n";
$ret .= "<message name=\"{$mname}_Response\">\n";
$ret .= " <part name=\"{$mname}_Response\" />\n";
$ret .= "</message>\n\n";
$ret .= "<portType name=\"{$mname}_PortType\">\n";
$ret .= " <operation name=\"{$mname}\">\n";
$ret .= " <input message=\"{$mname}\" />\n";
$ret .= " <output message=\"{$mname}_Response\" />\n";
$ret .= " </operation>\n";
$ret .= "</portType>\n\n";
$ret .= "<binding name=\"{$mname}_Binding\" type=\"{$mname}_PortType\">\n";
$ret .= " <soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" style=\"document\"/>\n";
$ret .= " <operation name=\"{$mname}\">\n";
$ret .= " <soap:operation soapAction=\"{$mname}\" />\n";
$ret .= " <input><soap:body use=\"literal\" /></input>\n";
$ret .= " <output><soap:body use=\"literal\" /></output>\n";
$ret .= " </operation>\n";
$ret .= "</binding>\n\n";
$ret .= "<service name=\"{$mname}\">\n";
$ret .= " <port name=\"{$mname}_PortType\" binding=\"{$mname}_Binding\">\n";
$ret .= " <soap:address location=\"{$base_href}/{$mname}\" />\n";
$ret .= "</service>\n\n";
$ret .= "</definitions>\n";
* Generates a XSD document for the specified method
$ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$ret .= "<xs:schema targetNamespace=\"urn:nssoap.{$method}_d\" xmlns=\"urn:nssoap.{$method}_d\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n";
$ret .= "<xs:element name=\"{$method}\">\n";
$ret .= " <xs:complexType>\n";
$ret .= " <xs:sequence>\n";
foreach ($this->exports[$method] as $param) $ret .= " <xs:element ref=\"{$param['name']}\"/>\n";
$ret .= " </xs:sequence>\n";
$ret .= " </xs:complexType>\n";
$ret .= "</xs:element>\n\n";
foreach ($this->exports[$method] as $param) {
$ret .= "<xs:element name=\"{$param['name']}\">\n";
if ($ptype = $param["type"]) {
$ret .= " <xs:simpleType>\n";
$ret .= " <xs:restriction base=\"xs:{$ptype}\" />\n";
$ret .= " </xs:simpleType>\n";
$ret .= "</xs:element>\n";
$ret .= "</xs:schema>\n";
if (isset ($this->exports[$umethod = $purl[0]])) {
if ((!isset ($purl[1])) || ($purl[1] === "call")) {
if ($x === false) return $this->Fault("unable to decode XML request");
$xdata = $x->Body->children("urn:nssoap." . $umethod . "_d");
$xdata = $x->children('http://schemas.xmlsoap.org/soap/envelope/')->Body;
list ($xmethod) = each($xdata);
$xargs = $xdata->children();
$method = (string) $xmethod;
if ($method !== $umethod) return $this->Fault("ambiguous method call ({$method} != {$umethod})");
foreach ($xargs as $k => $xv) {
if ((int) $v == (float) $v) {
if ($eargs = $this->exports[$method]) {
foreach ($eargs as $earg) {
foreach ($args as $k => $v) if ($earg["name"] === $k) {
$ret = $this->on_Call($method, $cargs);
return $this->Fault($e->getMessage());
return $this->Fault("undefined method");
return $this->Fault("could not find request block");
} else if ($purl[1] === "xsd") {
return $this->Fault("incorrect url");
} else if (($purl[0] === "wsdl") || ($purl[0] === "")) {
return $this->Fault("incorrect url");
* Event called on SOAP method call
* the value returned by on_Call() will be sent back as the SOAP method call response
abstract public function on_Call($method, $args);
|