nanoserv
[ class tree: nanoserv ] [ index: nanoserv ] [ all elements ]

Source for file NS_SOAP_Service_Handler.php

Documentation is available at NS_SOAP_Service_Handler.php

  1. <?php
  2.  
  3. /**
  4.  *
  5.  * nanoserv handlers - SOAP 1.1 over HTTP service handler
  6.  * 
  7.  * Copyright (C) 2004-2010 Vincent Negrier aka. sIX <six@aegis-corp.org>
  8.  * 
  9.  * This library is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Lesser General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2.1 of the License, or (at your option) any later version.
  13.  * 
  14.  * This library is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Lesser General Public License for more details.
  18.  * 
  19.  * You should have received a copy of the GNU Lesser General Public
  20.  * License along with this library; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA *
  22.  *
  23.  * @package nanoserv
  24.  * @subpackage Handlers
  25.  */
  26.  
  27. /**
  28.  * Require the HTTP server
  29.  */
  30. require_once "nanoserv-compat/handlers/NS_HTTP_Service_Handler.php";
  31.  
  32. /**
  33.  * SOAP 1.1 over HTTP Service handler class
  34.  *
  35.  * @package nanoserv
  36.  * @subpackage Handlers
  37.  * @since 1.0.2
  38.  */
  39. abstract class NS_SOAP_Service_Handler extends NS_HTTP_Service_Handler {
  40.  
  41.     /**
  42.      * Request URL
  43.      * @var string 
  44.      */
  45.     protected $request_url = "";
  46.     
  47.     /**
  48.      * Last called method name
  49.      * @var string 
  50.      */
  51.     protected $method_name;
  52.     
  53.     /**
  54.      * List of exported methods with their parameters
  55.      * @var array 
  56.      */
  57.     protected $exports;
  58.     
  59.     /**
  60.      * Defines the host name of the server, useful for WSDL automatic generation
  61.      * @var string 
  62.      */
  63.     protected $hostname;
  64.     
  65.     /**
  66.      * NS_SOAP_Service_Handler constructor
  67.      *
  68.      * The constructor here only builds the exports list for WSDL automatic generation
  69.      *
  70.      * @param array $options 
  71.      */
  72.     public function __construct($options{
  73.  
  74.         if (isset($options["hostname"])) {
  75.             
  76.             $this->hostname = $options["hostname"];
  77.  
  78.         }
  79.         
  80.         $this->exports = $this->Get_Exports();
  81.     
  82.     }
  83.     
  84.     /**
  85.      * Get list of exported methods with their parameters
  86.      *
  87.      * This methods needs to be overloaded and return the correct list in child classes
  88.      *
  89.      * @return array 
  90.      */
  91.     abstract public function Get_Exports();
  92.     
  93.     /**
  94.      * Convert a PHP variable to SOAP string representation
  95.      *
  96.      * @param string $var 
  97.      * @return string 
  98.      */
  99.     protected function Variable_To_SOAP_String($var$key=false{
  100.  
  101.         if (is_array($var)) {
  102.  
  103.             $ret "";
  104.             
  105.             foreach ($var as $k => $v{
  106.                 
  107.                 if (is_numeric($k&& ($key !== false)) $k $key "_member";
  108.  
  109.                 $ret .= "<{$k}>$this->Variable_To_SOAP_String($v$k"</{$k}>";
  110.  
  111.             }        
  112.  
  113.             return $ret;
  114.  
  115.         else {
  116.  
  117.             return utf8_encode($var);
  118.         
  119.         }
  120.  
  121.     }
  122.  
  123.     /**
  124.      * Add SOAP response envelope
  125.      *
  126.      * @param string $result 
  127.      * @return string 
  128.      */
  129.     protected function SOAP_Add_Response_Envelope($result{
  130.  
  131.         $this->Set_Content_Type("text/xml");
  132.         
  133.         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>";
  134.     
  135.     }
  136.     
  137.     /**
  138.      * Returns a correctly formatted SOAP fault result
  139.      *
  140.      * @param string $string 
  141.      * @param string $code 
  142.      * @return string 
  143.      */
  144.     protected function Fault($string$code="Server"{
  145.  
  146.         unset($this->method_name);
  147.         
  148.         return $this->SOAP_Add_Response_Envelope("<SOAP-ENV:Fault><faultcode>SOAP-ENV:{$code}</faultcode><faultstring>{$string}</faultstring></SOAP-ENV:Fault>");
  149.     
  150.     }
  151.     
  152.     /**
  153.      * Returns a base location for the HTTP service based on the hostname option and the listening port
  154.      *
  155.      * @return string 
  156.      */
  157.     protected function Get_Base_Href({
  158.         
  159.         $ret "http://";
  160.         
  161.         if ($this->hostname{
  162.  
  163.             $ret .= $this->hostname;
  164.             
  165.             if (substr($sn $this->socket->Get_Name()-3!== ":80"{
  166.  
  167.                 strtok($sn":");
  168.  
  169.                 $ret .= ":" strtok("");
  170.             
  171.             }
  172.  
  173.         else if (isset($this->request_headers["HOST"])) {
  174.  
  175.             $ret .= $this->request_headers["HOST"];
  176.             
  177.         else {
  178.  
  179.             $ret .= php_uname("n");
  180.  
  181.             if (substr($sn $this->socket->Get_Name()-3!== ":80"{
  182.  
  183.                 strtok($sn":");
  184.  
  185.                 $ret .= ":" strtok("");
  186.             
  187.             }
  188.     
  189.         }
  190.         
  191.         return $ret;
  192.     
  193.     }
  194.     
  195.     /**
  196.      * Generates a WSDL document for the current service
  197.      *
  198.      * @return string 
  199.      */
  200.     public function Get_WSDL({
  201.  
  202.         $classname get_class($this);
  203.         
  204.         $base_href $this->Get_Base_Href();
  205.         
  206.         $ret  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  207.         $ret .= "<definitions targetNamespace=\"urn:nssoap.{$classname}\"\n";
  208.         $ret .= "             xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n";
  209.         $ret .= "             xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
  210.         $ret .= "             xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n";
  211.         $ret .= "             xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"\n";
  212.  
  213.         $i 0;
  214.         
  215.         foreach (array_keys($this->exportsas $mname{
  216.         
  217.             $ret .= "             xmlns:xsd".(++$i)."=\"urn:nssoap.{$mname}_d\"\n";
  218.  
  219.         }
  220.  
  221.         $ret .= ">\n\n";
  222.  
  223.         $i 0;
  224.         
  225.         foreach (array_keys($this->exportsas $mname{
  226.  
  227.             $ret .= "<import namespace=\"urn:nssoap.{$mname}_d\" location=\"{$base_href}/{$mname}/xsd\" />\n\n";
  228.  
  229.             $ret .= "<message name=\"{$mname}\">\n";
  230.             $ret .= "   <part name=\"{$mname}\" element=\"xsd".(++$i).":{$mname}\" />\n";
  231.             $ret .= "</message>\n\n";
  232.  
  233.             $ret .= "<message name=\"{$mname}_Response\">\n";
  234.             $ret .= "   <part name=\"{$mname}_Response\" />\n";
  235.             $ret .= "</message>\n\n";
  236.  
  237.             $ret .= "<portType name=\"{$mname}_PortType\">\n";
  238.             $ret .= "   <operation name=\"{$mname}\">\n";
  239.             $ret .= "      <input message=\"{$mname}\" />\n";
  240.             $ret .= "      <output message=\"{$mname}_Response\" />\n";
  241.             $ret .= "   </operation>\n";
  242.             $ret .= "</portType>\n\n";
  243.  
  244.             $ret .= "<binding name=\"{$mname}_Binding\" type=\"{$mname}_PortType\">\n";
  245.             $ret .= "   <soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" style=\"document\"/>\n";
  246.             $ret .= "   <operation name=\"{$mname}\">\n";
  247.             $ret .= "       <soap:operation soapAction=\"{$mname}\" />\n";
  248.             $ret .= "       <input><soap:body use=\"literal\" /></input>\n";
  249.             $ret .= "       <output><soap:body use=\"literal\" /></output>\n";
  250.             $ret .= "   </operation>\n";
  251.             $ret .= "</binding>\n\n";
  252.  
  253.             $ret .= "<service name=\"{$mname}\">\n";
  254.             $ret .= "   <port name=\"{$mname}_PortType\" binding=\"{$mname}_Binding\">\n";
  255.             $ret .= "      <soap:address location=\"{$base_href}/{$mname}\" />\n";
  256.             $ret .= "   </port>\n";
  257.             $ret .= "</service>\n\n";
  258.  
  259.         }
  260.             
  261.         $ret .= "</definitions>\n";
  262.  
  263.         return $ret;    
  264.  
  265.     }
  266.     
  267.     /**
  268.      * Generates a XSD document for the specified method
  269.      *
  270.      * @param string $method 
  271.      * @return string 
  272.      */
  273.     public function Get_XSD($method{
  274.  
  275.         $classname get_class($this);
  276.         
  277.         $base_href $this->Get_Base_Href();
  278.         
  279.         $ret  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  280.         $ret .= "<xs:schema targetNamespace=\"urn:nssoap.{$method}_d\" xmlns=\"urn:nssoap.{$method}_d\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n";
  281.  
  282.         $ret .= "<xs:element name=\"{$method}\">\n";
  283.         $ret .= "    <xs:complexType>\n";
  284.         $ret .= "       <xs:sequence>\n";
  285.  
  286.         foreach ($this->exports[$methodas $param$ret .= "           <xs:element ref=\"{$param['name']}\"/>\n";
  287.         
  288.         $ret .= "       </xs:sequence>\n";
  289.         $ret .= "      </xs:complexType>\n";
  290.         $ret .= "</xs:element>\n\n";
  291.  
  292.         foreach ($this->exports[$methodas $param{
  293.  
  294.             $ret .= "<xs:element name=\"{$param['name']}\">\n";
  295.  
  296.             if ($ptype $param["type"]{
  297.  
  298.                 $ret .= "    <xs:simpleType>\n";
  299.                 $ret .= "        <xs:restriction base=\"xs:{$ptype}\" />\n";
  300.                 $ret .= "    </xs:simpleType>\n";
  301.             
  302.             }
  303.  
  304.             $ret .= "</xs:element>\n";
  305.         
  306.         }
  307.  
  308.         $ret .= "</xs:schema>\n";
  309.  
  310.         return $ret;
  311.     
  312.     }
  313.     
  314.     final public function on_Request($url{
  315.  
  316.         $this->request_url = $url;
  317.         
  318.         $purl explode("/"trim($url"/"));
  319.  
  320.         if (isset($this->exports[$umethod $purl[0]])) {
  321.  
  322.             if ((!isset($purl[1])) || ($purl[1=== "call")) {
  323.  
  324.                 // Method call
  325.             
  326.                 $x @simplexml_load_string($this->request_contentNULL0"http://schemas.xmlsoap.org/soap/envelope/");
  327.                 
  328.                 if ($x === falsereturn $this->Fault("unable to decode XML request");
  329.  
  330.                 if ($x->Body{
  331.  
  332.                     $xdata $x->Body->children("urn:nssoap." $umethod "_d");
  333.  
  334.                 else {
  335.  
  336.                     $xdata $x->children('http://schemas.xmlsoap.org/soap/envelope/')->Body;
  337.  
  338.                 }
  339.  
  340.                 list($xmethodeach($xdata);
  341.                 $xargs $xdata->children();
  342.  
  343.                 $method = (string)$xmethod;
  344.                 $args array();
  345.                 
  346.                 if ($method !== $umethodreturn $this->Fault("ambiguous method call ({$method} != {$umethod})");
  347.                 
  348.                 foreach ($xargs as $k => $xv{
  349.  
  350.                     $v = (string)$xv;
  351.                     
  352.                     if (is_numeric($v&& ($v{0!== "0")) {
  353.  
  354.                         if ((int)$v == (float)$v{
  355.  
  356.                             $args[$k= (int)$v;
  357.  
  358.                         else {
  359.  
  360.                             $args[$k= (float)$v;
  361.  
  362.                         }
  363.                     
  364.                     else {
  365.  
  366.                         $args[$k$v;
  367.                     
  368.                     }
  369.                     
  370.                 }
  371.                 
  372.                 if ($method{
  373.                     
  374.                     if ($eargs $this->exports[$method]{
  375.                     
  376.                         $apos 0;
  377.                         
  378.                         $cargs array();
  379.  
  380.                         foreach ($eargs as $earg{
  381.  
  382.                             foreach ($args as $k => $vif ($earg["name"=== $k{
  383.                                 
  384.                                 $cargs[$apos$v;
  385.  
  386.                                 break;
  387.  
  388.                             }
  389.                             
  390.                             ++$apos;
  391.                         
  392.                         }
  393.                         
  394.                         $this->method_name = $method;
  395.  
  396.                         try {
  397.  
  398.                             $ret $this->on_Call($method$cargs);
  399.  
  400.                         catch (Exception $e{
  401.  
  402.                             return $this->Fault($e->getMessage());
  403.  
  404.                         }
  405.  
  406.                     else {
  407.  
  408.                         // Fault
  409.  
  410.                         return $this->Fault("undefined method");
  411.                         
  412.                     }
  413.                 
  414.                 else {
  415.  
  416.                     // Fault
  417.                     
  418.                     return $this->Fault("could not find request block");
  419.  
  420.                 }
  421.  
  422.                 $this->Set_Content_Type("text/xml");
  423.  
  424.                 return $this->SOAP_Add_Response_Envelope("<{$method}_Response>".$this->Variable_To_SOAP_String($ret)."</{$method}_Response>");
  425.             
  426.             else if ($purl[1=== "xsd"{
  427.  
  428.                 // Export XSD
  429.  
  430.                 $this->Set_Content_Type("text/xml");
  431.  
  432.                 return $this->Get_XSD($purl[0]);
  433.  
  434.             else {
  435.  
  436.                 // Fault
  437.  
  438.                 return $this->Fault("incorrect url");
  439.             
  440.             }
  441.  
  442.         else if (($purl[0=== "wsdl"|| ($purl[0=== "")) {
  443.  
  444.             // Export WSDL
  445.  
  446.             $this->Set_Content_Type("text/xml");
  447.  
  448.             return $this->Get_WSDL();
  449.         
  450.         else {
  451.  
  452.             // Fault
  453.  
  454.             $this->Set_Response_Status(403);
  455.  
  456.             return $this->Fault("incorrect url");
  457.         
  458.         }
  459.         
  460.     }
  461.  
  462.     /**
  463.      * Event called on SOAP method call
  464.      *
  465.      * the value returned by on_Call() will be sent back as the SOAP method call response
  466.      *
  467.      * @param string $method 
  468.      * @param array $args 
  469.      * @return mixed 
  470.      */
  471.     abstract public function on_Call($method$args);
  472.  
  473. }
  474.  
  475. ?>

Documentation generated on Wed, 30 Nov 2011 22:03:25 +0100 by phpDocumentor 1.4.3