diff --git a/docs/api/test.xml b/docs/api/test.xml deleted file mode 100644 index e69de29..0000000 diff --git a/library/App/Webservice/Calls.php b/library/App/Webservice/Calls.php new file mode 100644 index 0000000..b78bcc8 --- /dev/null +++ b/library/App/Webservice/Calls.php @@ -0,0 +1,23 @@ +getService('stringReverser'); + return $srv->reverse($input); + } + +} diff --git a/library/Boilerplate/Webservice/Soap/Autodiscover.php b/library/Boilerplate/Webservice/Soap/Autodiscover.php new file mode 100644 index 0000000..a30c253 --- /dev/null +++ b/library/Boilerplate/Webservice/Soap/Autodiscover.php @@ -0,0 +1,147 @@ + 'string'); + + public function __construct($strategy = true, $uri=null) { + parent::__construct($strategy,$uri); + } + + /** + * overload the ZF method + * + * @param $function Zend_Server_Reflection_Function_Abstract function to add + * @param $wsdl Zend_Soap_Wsdl WSDL document + * @param $port object wsdl:portType + * @param $binding object wsdl:binding + * @return void + */ + protected function _addFunctionToWsdl($function, $wsdl, $port, $binding) + { + $uri = $this->getUri(); + + $prototype = null; + $maxNumArgumentsOfPrototype = -1; + foreach ($function->getPrototypes() as $tmpPrototype) { + $numParams = count($tmpPrototype->getParameters()); + if ($numParams > $maxNumArgumentsOfPrototype) { + $maxNumArgumentsOfPrototype = $numParams; + $prototype = $tmpPrototype; + } + } + if ($prototype === null) { + require_once "Zend/Soap/AutoDiscover/Exception.php"; + throw new \Zend_Soap_AutoDiscover_Exception("No prototypes could be found for the '" . $function->getName() . "' function"); + } + + // Add the input message (parameters) + $args = array(); + if ($this->_bindingStyle['style'] == 'document') { + // Document style: wrap all parameters in a sequence element + $sequence = array(); + foreach ($this->_extra_params as $param_name => $param_type) { + $sequenceElement = array( + 'name' => $param_name, + 'type' => $wsdl->getType($param_type) + ); + if (in_array($param_name,$this->_extra_optional)) { + $sequenceElement['nillable'] = 'true'; + } + $sequence[] = $sequenceElement; + } + foreach ($prototype->getParameters() as $param) { + $sequenceElement = array( + 'name' => $param->getName(), + 'type' => $wsdl->getType($param->getType()) + ); + if ($param->isOptional()) { + $sequenceElement['nillable'] = 'true'; + } + $sequence[] = $sequenceElement; + } + $element = array( + 'name' => $function->getName(), + 'sequence' => $sequence + ); + // Add the wrapper element part, which must be named 'parameters' + $args['parameters'] = array('element' => $wsdl->addElement($element)); + } else { + // RPC style: add each parameter as a typed part + foreach ($this->_extra_params as $param_name => $param_type) { + $args[$param_name] = array('type' => $wsdl->getType($param_type)); + } + foreach ($prototype->getParameters() as $param) { + $args[$param->getName()] = array('type' => $wsdl->getType($param->getType())); + } + } + $wsdl->addMessage($function->getName() . 'In', $args); + + $isOneWayMessage = false; + if($prototype->getReturnType() == "void") { + $isOneWayMessage = true; + } + + if($isOneWayMessage == false) { + // Add the output message (return value) + $args = array(); + if ($this->_bindingStyle['style'] == 'document') { + // Document style: wrap the return value in a sequence element + $sequence = array(); + if ($prototype->getReturnType() != "void") { + $sequence[] = array( + 'name' => $function->getName() . 'Result', + 'type' => $wsdl->getType($prototype->getReturnType()) + ); + } + if (isset($this->_extra_out)) { + foreach ($this->_extra_out as $out_name => $out_type) { + $sequence[] = array( + 'name' => $out_name . 'Result', + 'type' => $wsdl->getType($out_type) + ); + } + } + + $element = array( + 'name' => $function->getName() . 'Response', + 'sequence' => $sequence + ); + // Add the wrapper element part, which must be named 'parameters' + $args['parameters'] = array('element' => $wsdl->addElement($element)); + } else if ($prototype->getReturnType() != "void") { + // RPC style: add the return value as a typed part + $args['return'] = array('type' => $wsdl->getType($prototype->getReturnType())); + } + $wsdl->addMessage($function->getName() . 'Out', $args); + } + + // Add the portType operation + if($isOneWayMessage == false) { + $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', 'tns:' . $function->getName() . 'Out'); + } else { + $portOperation = $wsdl->addPortOperation($port, $function->getName(), 'tns:' . $function->getName() . 'In', false); + } + $desc = $function->getDescription(); + if (strlen($desc) > 0) { + //$wsdl->addDocumentation($portOperation, $desc); + } + + // When using the RPC style, make sure the operation style includes a 'namespace' attribute (WS-I Basic Profile 1.1 R2717) + if ($this->_bindingStyle['style'] == 'rpc' && !isset($this->_operationBodyStyle['namespace'])) { + $this->_operationBodyStyle['namespace'] = ''.$uri; + } + + // Add the binding operation + $operation = $wsdl->addBindingOperation($binding, $function->getName(), $this->_operationBodyStyle, $this->_operationBodyStyle); + $wsdl->addSoapOperation($operation, $uri . '#' .$function->getName()); + + // Add the function name to the list + $this->_functions[] = $function->getName(); + } + + + +} diff --git a/library/Boilerplate/Webservice/Soap/Server.php b/library/Boilerplate/Webservice/Soap/Server.php new file mode 100644 index 0000000..873e08e --- /dev/null +++ b/library/Boilerplate/Webservice/Soap/Server.php @@ -0,0 +1,99 @@ +_getSoap(); + $soap->fault(401 , 'Message contains no XML'); + } + + $dom = new \DOMDocument(); + if(!$dom->loadXML($request)) { + $soap = $this->_getSoap(); + $soap->fault(401 , 'Message contains invalid XML'); + } else { + //strip out api_key stuff + $xml = simplexml_load_string($request); + $url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']; + + $children = (array) $xml->children('http://schemas.xmlsoap.org/soap/envelope/') + ->Body + ->children($url); + + $methods = array_keys($children); + $method = $methods[0]; + + $soap = $this->_getSoap(); + + $apikey = (string) $xml->children('http://schemas.xmlsoap.org/soap/envelope/') + ->Body + ->children($url) + ->{$method} + ->children() + ->apikey; + + if ($this->_hasAccess($apikey, $method)) { + //strip api info + unset($xml->children('http://schemas.xmlsoap.org/soap/envelope/') + ->Body + ->children($url) + ->{$method} + ->children() + ->apikey); + + $request = $xml->asXml(); + + //remove whitespace & empty lines + $request = trim($request); + $request = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $request); + return parent::handle($request); + } else { + $soap = $this->_getSoap(); + $soap->fault(403 , 'Access forbidden'); + } + } + } + + /** + * check if apikey has access to method + * + * @param string $apikey + * @param string $method + * @return bool + */ + protected function _hasAccess($apikey, $method) { + return in_array($apikey, $this->allowedKeys); + } + +} + + diff --git a/public/ws/soap.php b/public/ws/soap.php new file mode 100644 index 0000000..57d3305 --- /dev/null +++ b/public/ws/soap.php @@ -0,0 +1,49 @@ +registerNamespace('Boilerplate_'); +$l->registerNamespace('Elastica_'); +include "App/Webservice/Calls.php"; //? + +// Create application, bootstrap, and run +$application = new Zend_Application( + APPLICATION_ENV, + APPLICATION_PATH . '/configs/application.ini' +); + +$application->bootstrap(); + +ini_set("soap.wsdl_cache_enabled", 0);//for development +if (isset($_GET['WSDL'])) { + // Auto generate WSDL + $autodiscover = new \Boilerplate\Webservice\Soap\AutoDiscover(); + //$autodiscover = new Zend_Soap_AutoDiscover(); + // Set endpoint URL + $autodiscover->setUri('http://localhost:8080/ws/soap.php'); + $autodiscover->setClass("\\App\\Webservice\\Calls"); + $autodiscover->handle(); +} elseif (isset($_GET['INTERNALWSDL'])) { + $autodiscover = new Zend_Soap_AutoDiscover(); + $autodiscover->setClass('\\App\\Webservice\\Calls'); + $autodiscover->setUri('http://localhost:8080/ws/soap.php'); + $autodiscover->handle(); +} else { + $options = array('soap_version' => SOAP_1_2); + $server = new \Boilerplate\Webservice\Soap\Server('http://localhost/ws/soap.php?INTERNALWSDL=1', $options); + $server->setObject(new \App\Webservice\Calls()); + $server->handle(); +} \ No newline at end of file