Merge pull request #3 from aschamberger/master
Basic support for MTOM/SwA, WS-Adressing and WS-Security
This commit is contained in:
commit
23ba025ffe
|
@ -1 +1,5 @@
|
||||||
vendor
|
vendor
|
||||||
|
/phpunit.xml
|
||||||
|
.buildpath
|
||||||
|
.project
|
||||||
|
.settings
|
|
@ -0,0 +1,313 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cURL wrapper class for doing HTTP requests that uses the soap class options.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class Curl
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* HTTP User Agent.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const USER_AGENT = 'PHP-SOAP/\BeSimple\SoapClient';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Curl resource.
|
||||||
|
*
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private $ch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum number of location headers to follow.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $followLocationMaxRedirects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request response data.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param array $options Options array from SoapClient constructor
|
||||||
|
* @param int $followLocationMaxRedirects Redirection limit for Location header
|
||||||
|
*/
|
||||||
|
public function __construct(array $options = array(), $followLocationMaxRedirects = 10)
|
||||||
|
{
|
||||||
|
// set the default HTTP user agent
|
||||||
|
if (!isset($options['user_agent'])) {
|
||||||
|
$options['user_agent'] = self::USER_AGENT;
|
||||||
|
}
|
||||||
|
$this->followLocationMaxRedirects = $followLocationMaxRedirects;
|
||||||
|
|
||||||
|
// make http request
|
||||||
|
$this->ch = curl_init();
|
||||||
|
$curlOptions = array(
|
||||||
|
CURLOPT_ENCODING => '',
|
||||||
|
CURLOPT_SSL_VERIFYPEER => false,
|
||||||
|
CURLOPT_FAILONERROR => false,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
|
||||||
|
CURLOPT_HEADER => true,
|
||||||
|
CURLOPT_USERAGENT => $options['user_agent'],
|
||||||
|
CURLINFO_HEADER_OUT => true,
|
||||||
|
);
|
||||||
|
curl_setopt_array($this->ch, $curlOptions);
|
||||||
|
if (isset($options['compression']) && !($options['compression'] & SOAP_COMPRESSION_ACCEPT)) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_ENCODING, 'identity');
|
||||||
|
}
|
||||||
|
if (isset($options['connection_timeout'])) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_CONNECTTIMEOUT, $options['connection_timeout']);
|
||||||
|
}
|
||||||
|
if (isset($options['proxy_host'])) {
|
||||||
|
$port = isset($options['proxy_port']) ? $options['proxy_port'] : 8080;
|
||||||
|
curl_setopt($this->ch, CURLOPT_PROXY, $options['proxy_host'] . ':' . $port);
|
||||||
|
}
|
||||||
|
if (isset($options['proxy_user'])) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_PROXYUSERPWD, $options['proxy_user'] . ':' . $options['proxy_password']);
|
||||||
|
}
|
||||||
|
if (isset($options['login'])) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
|
||||||
|
curl_setopt($this->ch, CURLOPT_USERPWD, $options['login'].':'.$options['password']);
|
||||||
|
}
|
||||||
|
if (isset($options['local_cert'])) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_SSLCERT, $options['local_cert']);
|
||||||
|
curl_setopt($this->ch, CURLOPT_SSLCERTPASSWD, $options['passphrase']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor.
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
curl_close($this->ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute HTTP request.
|
||||||
|
* Returns true if request was successfull.
|
||||||
|
*
|
||||||
|
* @param string $location HTTP location
|
||||||
|
* @param string $request Request body
|
||||||
|
* @param array $requestHeaders Request header strings
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function exec($location, $request = null, $requestHeaders = array())
|
||||||
|
{
|
||||||
|
curl_setopt($this->ch, CURLOPT_URL, $location);
|
||||||
|
|
||||||
|
if (!is_null($request)) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($requestHeaders) > 0) {
|
||||||
|
curl_setopt($this->ch, CURLOPT_HTTPHEADER, $requestHeaders);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response = $this->execManualRedirect($this->followLocationMaxRedirects);
|
||||||
|
|
||||||
|
return ($this->response === false) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom curl_exec wrapper that allows to follow redirects when specific
|
||||||
|
* http response code is set. SOAP only allows 307.
|
||||||
|
*
|
||||||
|
* @param int $redirects Current redirection count
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
private function execManualRedirect($redirects = 0)
|
||||||
|
{
|
||||||
|
if ($redirects > $this->followLocationMaxRedirects) {
|
||||||
|
|
||||||
|
// TODO Redirection limit reached, aborting
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
curl_setopt($this->ch, CURLOPT_HEADER, true);
|
||||||
|
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$response = curl_exec($this->ch);
|
||||||
|
$httpResponseCode = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
|
||||||
|
if ($httpResponseCode == 307) {
|
||||||
|
$headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
|
||||||
|
$header = substr($response, 0, $headerSize);
|
||||||
|
$matches = array();
|
||||||
|
preg_match('/Location:(.*?)\n/', $header, $matches);
|
||||||
|
$url = trim(array_pop($matches));
|
||||||
|
// @parse_url to suppress E_WARNING for invalid urls
|
||||||
|
if (($url = @parse_url($url)) !== false) {
|
||||||
|
$lastUrl = parse_url(curl_getinfo($this->ch, CURLINFO_EFFECTIVE_URL));
|
||||||
|
if (!isset($url['scheme'])) {
|
||||||
|
$url['scheme'] = $lastUrl['scheme'];
|
||||||
|
}
|
||||||
|
if (!isset($url['host'])) {
|
||||||
|
$url['host'] = $lastUrl['host'];
|
||||||
|
}
|
||||||
|
if (!isset($url['path'])) {
|
||||||
|
$url['path'] = $lastUrl['path'];
|
||||||
|
}
|
||||||
|
$newUrl = $url['scheme'] . '://' . $url['host'] . $url['path'] . ($url['query'] ? '?' . $url['query'] : '');
|
||||||
|
curl_setopt($this->ch, CURLOPT_URL, $newUrl);
|
||||||
|
|
||||||
|
return $this->execManualRedirect($redirects++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error code mapping from cURL error codes to PHP ext/soap error messages
|
||||||
|
* (where applicable)
|
||||||
|
*
|
||||||
|
* http://curl.haxx.se/libcurl/c/libcurl-errors.html
|
||||||
|
*
|
||||||
|
* @return array(int=>string)
|
||||||
|
*/
|
||||||
|
protected function getErrorCodeMapping()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
1 => 'Unknown protocol. Only http and https are allowed.', //CURLE_UNSUPPORTED_PROTOCOL
|
||||||
|
3 => 'Unable to parse URL', //CURLE_URL_MALFORMAT
|
||||||
|
5 => 'Could not connect to host', //CURLE_COULDNT_RESOLVE_PROXY
|
||||||
|
6 => 'Could not connect to host', //CURLE_COULDNT_RESOLVE_HOST
|
||||||
|
7 => 'Could not connect to host', //CURLE_COULDNT_CONNECT
|
||||||
|
9 => 'Could not connect to host', //CURLE_REMOTE_ACCESS_DENIED
|
||||||
|
28 => 'Failed Sending HTTP SOAP request', //CURLE_OPERATION_TIMEDOUT
|
||||||
|
35 => 'Could not connect to host', //CURLE_SSL_CONNECT_ERROR
|
||||||
|
41 => 'Can\'t uncompress compressed response', //CURLE_FUNCTION_NOT_FOUND
|
||||||
|
51 => 'Could not connect to host', //CURLE_PEER_FAILED_VERIFICATION
|
||||||
|
52 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_GOT_NOTHING
|
||||||
|
53 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_NOTFOUND
|
||||||
|
54 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_SETFAILED
|
||||||
|
55 => 'Failed Sending HTTP SOAP request', //CURLE_SEND_ERROR
|
||||||
|
56 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_RECV_ERROR
|
||||||
|
58 => 'Could not connect to host', //CURLE_SSL_CERTPROBLEM
|
||||||
|
59 => 'Could not connect to host', //CURLE_SSL_CIPHER
|
||||||
|
60 => 'Could not connect to host', //CURLE_SSL_CACERT
|
||||||
|
61 => 'Unknown Content-Encoding', //CURLE_BAD_CONTENT_ENCODING
|
||||||
|
65 => 'Failed Sending HTTP SOAP request', //CURLE_SEND_FAIL_REWIND
|
||||||
|
66 => 'SSL support is not available in this build', //CURLE_SSL_ENGINE_INITFAILED
|
||||||
|
67 => 'Could not connect to host', //CURLE_LOGIN_DENIED
|
||||||
|
77 => 'Could not connect to host', //CURLE_SSL_CACERT_BADFILE
|
||||||
|
80 => 'Error Fetching http body, No Content-Length, connection closed or chunked data', //CURLE_SSL_SHUTDOWN_FAILED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the curl error message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getErrorMessage()
|
||||||
|
{
|
||||||
|
$errorCodeMapping = $this->getErrorCodeMapping();
|
||||||
|
$errorNumber = curl_errno($this->ch);
|
||||||
|
if (isset($errorCodeMapping[$errorNumber])) {
|
||||||
|
|
||||||
|
return $errorCodeMapping[$errorNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
return curl_error($this->ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the request headers as a string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getRequestHeaders()
|
||||||
|
{
|
||||||
|
return curl_getinfo($this->ch, CURLINFO_HEADER_OUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the whole response (including headers) as a string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponse()
|
||||||
|
{
|
||||||
|
return $this->response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the response body as a string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponseBody()
|
||||||
|
{
|
||||||
|
$headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
|
||||||
|
|
||||||
|
return substr($this->response, $headerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the response content type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponseContentType()
|
||||||
|
{
|
||||||
|
return curl_getinfo($this->ch, CURLINFO_CONTENT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the response headers as a string.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponseHeaders()
|
||||||
|
{
|
||||||
|
$headerSize = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
|
||||||
|
|
||||||
|
return substr($this->response, 0, $headerSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the response http status code.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponseStatusCode()
|
||||||
|
{
|
||||||
|
return curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the response http status message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getResponseStatusMessage()
|
||||||
|
{
|
||||||
|
preg_match('/HTTP\/(1\.[0-1]+) ([0-9]{3}) (.*)/', $this->response, $matches);
|
||||||
|
|
||||||
|
return trim(array_pop($matches));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,138 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\Helper;
|
||||||
|
use BeSimple\SoapCommon\Mime\MultiPart as MimeMultiPart;
|
||||||
|
use BeSimple\SoapCommon\Mime\Parser as MimeParser;
|
||||||
|
use BeSimple\SoapCommon\Mime\Part as MimePart;
|
||||||
|
use BeSimple\SoapCommon\SoapRequest;
|
||||||
|
use BeSimple\SoapCommon\SoapRequestFilter;
|
||||||
|
use BeSimple\SoapCommon\SoapResponse;
|
||||||
|
use BeSimple\SoapCommon\SoapResponseFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MIME filter.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class MimeFilter implements SoapRequestFilter, SoapResponseFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Attachment type.
|
||||||
|
*
|
||||||
|
* @var int Helper::ATTACHMENTS_TYPE_SWA | Helper::ATTACHMENTS_TYPE_MTOM
|
||||||
|
*/
|
||||||
|
protected $attachmentType = Helper::ATTACHMENTS_TYPE_SWA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param int $attachmentType Helper::ATTACHMENTS_TYPE_SWA | Helper::ATTACHMENTS_TYPE_MTOM
|
||||||
|
*/
|
||||||
|
public function __construct($attachmentType)
|
||||||
|
{
|
||||||
|
$this->attachmentType = $attachmentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all properties to default values.
|
||||||
|
*/
|
||||||
|
public function resetFilter()
|
||||||
|
{
|
||||||
|
$this->attachmentType = Helper::ATTACHMENTS_TYPE_SWA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given request XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapRequest $request SOAP request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterRequest(SoapRequest $request)
|
||||||
|
{
|
||||||
|
// get attachments from request object
|
||||||
|
$attachmentsToSend = $request->getAttachments();
|
||||||
|
|
||||||
|
// build mime message if we have attachments
|
||||||
|
if (count($attachmentsToSend) > 0) {
|
||||||
|
$multipart = new MimeMultiPart();
|
||||||
|
$soapPart = new MimePart($request->getContent(), 'text/xml', 'utf-8', MimePart::ENCODING_EIGHT_BIT);
|
||||||
|
$soapVersion = $request->getVersion();
|
||||||
|
// change content type headers for MTOM with SOAP 1.1
|
||||||
|
if ($soapVersion == SOAP_1_1 && $this->attachmentType & Helper::ATTACHMENTS_TYPE_MTOM) {
|
||||||
|
$multipart->setHeader('Content-Type', 'type', 'application/xop+xml');
|
||||||
|
$multipart->setHeader('Content-Type', 'start-info', 'text/xml');
|
||||||
|
$soapPart->setHeader('Content-Type', 'application/xop+xml');
|
||||||
|
$soapPart->setHeader('Content-Type', 'type', 'text/xml');
|
||||||
|
}
|
||||||
|
// change content type headers for SOAP 1.2
|
||||||
|
elseif ($soapVersion == SOAP_1_2) {
|
||||||
|
$multipart->setHeader('Content-Type', 'type', 'application/soap+xml');
|
||||||
|
$soapPart->setHeader('Content-Type', 'application/soap+xml');
|
||||||
|
}
|
||||||
|
$multipart->addPart($soapPart, true);
|
||||||
|
foreach ($attachmentsToSend as $cid => $attachment) {
|
||||||
|
$multipart->addPart($attachment, false);
|
||||||
|
}
|
||||||
|
$request->setContent($multipart->getMimeMessage());
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
$headers = $multipart->getHeadersForHttp();
|
||||||
|
list($name, $contentType) = explode(': ', $headers[0]);
|
||||||
|
|
||||||
|
$request->setContentType($contentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given response XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapResponse $response SOAP response
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterResponse(SoapResponse $response)
|
||||||
|
{
|
||||||
|
// array to store attachments
|
||||||
|
$attachmentsRecieved = array();
|
||||||
|
|
||||||
|
// check content type if it is a multipart mime message
|
||||||
|
$responseContentType = $response->getContentType();
|
||||||
|
if (false !== stripos($responseContentType, 'multipart/related')) {
|
||||||
|
// parse mime message
|
||||||
|
$headers = array(
|
||||||
|
'Content-Type' => trim($responseContentType),
|
||||||
|
);
|
||||||
|
$multipart = MimeParser::parseMimeMessage($response->getContent(), $headers);
|
||||||
|
// get soap payload and update SoapResponse object
|
||||||
|
$soapPart = $multipart->getPart();
|
||||||
|
// convert href -> myhref for external references as PHP throws exception in this case
|
||||||
|
// http://svn.php.net/viewvc/php/php-src/branches/PHP_5_4/ext/soap/php_encoding.c?view=markup#l3436
|
||||||
|
$content = preg_replace('/href=(?!#)/', 'myhref=', $soapPart->getContent());
|
||||||
|
$response->setContent($content);
|
||||||
|
$response->setContentType($soapPart->getHeader('Content-Type'));
|
||||||
|
// store attachments
|
||||||
|
$attachments = $multipart->getParts(false);
|
||||||
|
foreach ($attachments as $cid => $attachment) {
|
||||||
|
$attachmentsRecieved[$cid] = $attachment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add attachments to response object
|
||||||
|
if (count($attachmentsRecieved) > 0) {
|
||||||
|
$response->setAttachments($attachmentsRecieved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,322 @@
|
||||||
|
|
||||||
namespace BeSimple\SoapClient;
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\Helper;
|
||||||
|
use BeSimple\SoapCommon\SoapKernel;
|
||||||
|
use BeSimple\SoapCommon\Converter\MtomTypeConverter;
|
||||||
|
use BeSimple\SoapCommon\Converter\SwaTypeConverter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Francis Besset <francis.besset@gmail.com>
|
* Extended SoapClient that uses a a cURL wrapper for all underlying HTTP
|
||||||
|
* requests in order to use proper authentication for all requests. This also
|
||||||
|
* adds NTLM support. A custom WSDL downloader resolves remote xsd:includes and
|
||||||
|
* allows caching of all remote referenced items.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
*/
|
*/
|
||||||
class SoapClient extends \SoapClient
|
class SoapClient extends \SoapClient
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Soap version.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $soapVersion = SOAP_1_1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracing enabled?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $tracingEnabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cURL instance.
|
||||||
|
*
|
||||||
|
* @var \BeSimple\SoapClient\Curl
|
||||||
|
*/
|
||||||
|
protected $curl = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last request headers.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $lastRequestHeaders = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last request.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $lastRequest = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last response headers.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $lastResponseHeaders = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last response.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $lastResponse = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last response.
|
||||||
|
*
|
||||||
|
* @var \BeSimple\SoapCommon\SoapKernel
|
||||||
|
*/
|
||||||
|
protected $soapKernel = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param string $wsdl WSDL file
|
||||||
|
* @param array(string=>mixed) $options Options array
|
||||||
|
*/
|
||||||
|
public function __construct($wsdl, array $options = array())
|
||||||
|
{
|
||||||
|
// tracing enabled: store last request/response header and body
|
||||||
|
if (isset($options['trace']) && $options['trace'] === true) {
|
||||||
|
$this->tracingEnabled = true;
|
||||||
|
}
|
||||||
|
// store SOAP version
|
||||||
|
if (isset($options['soap_version'])) {
|
||||||
|
$this->soapVersion = $options['soap_version'];
|
||||||
|
}
|
||||||
|
$this->curl = new Curl($options);
|
||||||
|
$wsdlFile = $this->loadWsdl($wsdl, $options);
|
||||||
|
// TODO $wsdlHandler = new WsdlHandler($wsdlFile, $this->soapVersion);
|
||||||
|
$this->soapKernel = new SoapKernel();
|
||||||
|
// set up type converter and mime filter
|
||||||
|
$this->configureMime($options);
|
||||||
|
// we want the exceptions option to be set
|
||||||
|
$options['exceptions'] = true;
|
||||||
|
// disable obsolete trace option for native SoapClient as we need to do our own tracing anyways
|
||||||
|
$options['trace'] = false;
|
||||||
|
// disable WSDL caching as we handle WSDL caching for remote URLs ourself
|
||||||
|
$options['cache_wsdl'] = WSDL_CACHE_NONE;
|
||||||
|
parent::__construct($wsdlFile, $options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform HTTP request with cURL.
|
||||||
|
*
|
||||||
|
* @param SoapRequest $soapRequest SoapRequest object
|
||||||
|
*
|
||||||
|
* @return SoapResponse
|
||||||
|
*/
|
||||||
|
private function __doHttpRequest(SoapRequest $soapRequest)
|
||||||
|
{
|
||||||
|
// HTTP headers
|
||||||
|
$headers = array(
|
||||||
|
'Content-Type:' . $soapRequest->getContentType(),
|
||||||
|
'SOAPAction: "' . $soapRequest->getAction() . '"',
|
||||||
|
);
|
||||||
|
// execute HTTP request with cURL
|
||||||
|
$responseSuccessfull = $this->curl->exec(
|
||||||
|
$soapRequest->getLocation(),
|
||||||
|
$soapRequest->getContent(),
|
||||||
|
$headers
|
||||||
|
);
|
||||||
|
// tracing enabled: store last request header and body
|
||||||
|
if ($this->tracingEnabled === true) {
|
||||||
|
$this->lastRequestHeaders = $this->curl->getRequestHeaders();
|
||||||
|
$this->lastRequest = $soapRequest->getContent();
|
||||||
|
}
|
||||||
|
// in case of an error while making the http request throw a soapFault
|
||||||
|
if ($responseSuccessfull === false) {
|
||||||
|
// get error message from curl
|
||||||
|
$faultstring = $this->curl->getErrorMessage();
|
||||||
|
throw new \SoapFault('HTTP', $faultstring);
|
||||||
|
}
|
||||||
|
// tracing enabled: store last response header and body
|
||||||
|
if ($this->tracingEnabled === true) {
|
||||||
|
$this->lastResponseHeaders = $this->curl->getResponseHeaders();
|
||||||
|
$this->lastResponse = $this->curl->getResponseBody();
|
||||||
|
}
|
||||||
|
// wrap response data in SoapResponse object
|
||||||
|
$soapResponse = SoapResponse::create(
|
||||||
|
$this->curl->getResponseBody(),
|
||||||
|
$soapRequest->getLocation(),
|
||||||
|
$soapRequest->getAction(),
|
||||||
|
$soapRequest->getVersion(),
|
||||||
|
$this->curl->getResponseContentType()
|
||||||
|
);
|
||||||
|
|
||||||
|
return $soapResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom request method to be able to modify the SOAP messages.
|
||||||
|
* $oneWay parameter is not used at the moment.
|
||||||
|
*
|
||||||
|
* @param string $request Request string
|
||||||
|
* @param string $location Location
|
||||||
|
* @param string $action SOAP action
|
||||||
|
* @param int $version SOAP version
|
||||||
|
* @param int $oneWay 0|1
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __doRequest($request, $location, $action, $version, $oneWay = 0)
|
||||||
|
{
|
||||||
|
// wrap request data in SoapRequest object
|
||||||
|
$soapRequest = SoapRequest::create($request, $location, $action, $version);
|
||||||
|
|
||||||
|
// do actual SOAP request
|
||||||
|
$soapResponse = $this->__doRequest2($soapRequest);
|
||||||
|
|
||||||
|
// return SOAP response to ext/soap
|
||||||
|
return $soapResponse->getContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the currently registered request filters on the request, performs
|
||||||
|
* the HTTP request and runs the response filters.
|
||||||
|
*
|
||||||
|
* @param SoapRequest $soapRequest SOAP request object
|
||||||
|
*
|
||||||
|
* @return SoapResponse
|
||||||
|
*/
|
||||||
|
protected function __doRequest2(SoapRequest $soapRequest)
|
||||||
|
{
|
||||||
|
// run SoapKernel on SoapRequest
|
||||||
|
$this->soapKernel->filterRequest($soapRequest);
|
||||||
|
|
||||||
|
// perform HTTP request with cURL
|
||||||
|
$soapResponse = $this->__doHttpRequest($soapRequest);
|
||||||
|
|
||||||
|
// run SoapKernel on SoapResponse
|
||||||
|
$this->soapKernel->filterResponse($soapResponse);
|
||||||
|
|
||||||
|
return $soapResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last request HTTP headers.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __getLastRequestHeaders()
|
||||||
|
{
|
||||||
|
return $this->lastRequestHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last request HTTP body.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __getLastRequest()
|
||||||
|
{
|
||||||
|
return $this->lastRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last response HTTP headers.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __getLastResponseHeaders()
|
||||||
|
{
|
||||||
|
return $this->lastResponseHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last response HTTP body.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __getLastResponse()
|
||||||
|
{
|
||||||
|
return $this->lastResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get SoapKernel instance.
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapCommon\SoapKernel
|
||||||
|
*/
|
||||||
|
public function getSoapKernel()
|
||||||
|
{
|
||||||
|
return $this->soapKernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure filter and type converter for SwA/MTOM.
|
||||||
|
*
|
||||||
|
* @param array &$options SOAP constructor options array.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function configureMime(array &$options)
|
||||||
|
{
|
||||||
|
if (isset($options['attachment_type']) && Helper::ATTACHMENTS_TYPE_BASE64 !== $options['attachment_type']) {
|
||||||
|
// register mime filter in SoapKernel
|
||||||
|
$mimeFilter = new MimeFilter($options['attachment_type']);
|
||||||
|
$this->soapKernel->registerFilter($mimeFilter);
|
||||||
|
// configure type converter
|
||||||
|
if (Helper::ATTACHMENTS_TYPE_SWA === $options['attachment_type']) {
|
||||||
|
$converter = new SwaTypeConverter();
|
||||||
|
$converter->setKernel($this->soapKernel);
|
||||||
|
} elseif (Helper::ATTACHMENTS_TYPE_MTOM === $options['attachment_type']) {
|
||||||
|
$converter = new MtomTypeConverter();
|
||||||
|
$converter->setKernel($this->soapKernel);
|
||||||
|
}
|
||||||
|
// configure typemap
|
||||||
|
if (!isset($options['typemap'])) {
|
||||||
|
$options['typemap'] = array();
|
||||||
|
}
|
||||||
|
$soapKernel = $this->soapKernel;
|
||||||
|
$options['typemap'][] = array(
|
||||||
|
'type_name' => $converter->getTypeName(),
|
||||||
|
'type_ns' => $converter->getTypeNamespace(),
|
||||||
|
'from_xml' => function($input) use ($converter) {
|
||||||
|
return $converter->convertXmlToPhp($input);
|
||||||
|
},
|
||||||
|
'to_xml' => function($input) use ($converter) {
|
||||||
|
return $converter->convertPhpToXml($input);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads WSDL files with cURL. Uses all SoapClient options for
|
||||||
|
* authentication. Uses the WSDL_CACHE_* constants and the 'soap.wsdl_*'
|
||||||
|
* ini settings. Does only file caching as SoapClient only supports a file
|
||||||
|
* name parameter.
|
||||||
|
*
|
||||||
|
* @param string $wsdl WSDL file
|
||||||
|
* @param array(string=>mixed) $options Options array
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function loadWsdl($wsdl, array $options)
|
||||||
|
{
|
||||||
|
// option to resolve wsdl/xsd includes
|
||||||
|
$resolveRemoteIncludes = true;
|
||||||
|
if (isset($options['resolve_wsdl_remote_includes'])) {
|
||||||
|
$resolveRemoteIncludes = $options['resolve_wsdl_remote_includes'];
|
||||||
|
}
|
||||||
|
// option to enable cache
|
||||||
|
$wsdlCache = WSDL_CACHE_DISK;
|
||||||
|
if (isset($options['cache_wsdl'])) {
|
||||||
|
$wsdlCache = $options['cache_wsdl'];
|
||||||
|
}
|
||||||
|
$wsdlDownloader = new WsdlDownloader($this->curl, $resolveRemoteIncludes, $wsdlCache);
|
||||||
|
try {
|
||||||
|
$cacheFileName = $wsdlDownloader->download($wsdl);
|
||||||
|
} catch (\RuntimeException $e) {
|
||||||
|
throw new \SoapFault('WSDL', "SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl . "' : failed to load external entity \"" . $wsdl . "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cacheFileName;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -15,25 +15,35 @@ namespace BeSimple\SoapClient;
|
||||||
use BeSimple\SoapCommon\AbstractSoapBuilder;
|
use BeSimple\SoapCommon\AbstractSoapBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Fluent interface builder for SoapClient instance.
|
||||||
|
*
|
||||||
* @author Francis Besset <francis.besset@gmail.com>
|
* @author Francis Besset <francis.besset@gmail.com>
|
||||||
* @author Christian Kerl <christian-kerl@web.de>
|
* @author Christian Kerl <christian-kerl@web.de>
|
||||||
*/
|
*/
|
||||||
class SoapClientBuilder extends AbstractSoapBuilder
|
class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Authentication options.
|
||||||
|
*
|
||||||
|
* @var array(string=>mixed)
|
||||||
|
*/
|
||||||
protected $soapOptionAuthentication = array();
|
protected $soapOptionAuthentication = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Create new instance with default options.
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
static public function createWithDefaults()
|
public static function createWithDefaults()
|
||||||
{
|
{
|
||||||
return parent::createWithDefaults()
|
return parent::createWithDefaults()
|
||||||
->withUserAgent('BeSimpleSoap')
|
->withUserAgent('BeSimpleSoap');
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClient
|
* Finally returns a SoapClient instance.
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClient
|
||||||
*/
|
*/
|
||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
|
@ -42,13 +52,22 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
return new SoapClient($this->wsdl, $this->getSoapOptions());
|
return new SoapClient($this->wsdl, $this->getSoapOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get final array of SOAP options.
|
||||||
|
*
|
||||||
|
* @return array(string=>mixed)
|
||||||
|
*/
|
||||||
public function getSoapOptions()
|
public function getSoapOptions()
|
||||||
{
|
{
|
||||||
return parent::getSoapOptions() + $this->soapOptionAuthentication;
|
return parent::getSoapOptions() + $this->soapOptionAuthentication;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Configure option 'trace'.
|
||||||
|
*
|
||||||
|
* @param boolean $trace Enable/Disable
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
public function withTrace($trace = true)
|
public function withTrace($trace = true)
|
||||||
{
|
{
|
||||||
|
@ -58,7 +77,11 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Configure option 'exceptions'.
|
||||||
|
*
|
||||||
|
* @param boolean $exceptions Enable/Disable
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
public function withExceptions($exceptions = true)
|
public function withExceptions($exceptions = true)
|
||||||
{
|
{
|
||||||
|
@ -68,7 +91,11 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Configure option 'user_agent'.
|
||||||
|
*
|
||||||
|
* @param string $userAgent User agent string
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
public function withUserAgent($userAgent)
|
public function withUserAgent($userAgent)
|
||||||
{
|
{
|
||||||
|
@ -77,18 +104,37 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable gzip compression.
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
|
*/
|
||||||
public function withCompressionGzip()
|
public function withCompressionGzip()
|
||||||
{
|
{
|
||||||
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP;
|
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP;
|
||||||
}
|
|
||||||
|
|
||||||
public function withCompressionDeflate()
|
return $this;
|
||||||
{
|
|
||||||
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Enable deflate compression.
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
|
*/
|
||||||
|
public function withCompressionDeflate()
|
||||||
|
{
|
||||||
|
$this->soapOptions['compression'] = SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure basic authentication
|
||||||
|
*
|
||||||
|
* @param string $username Username
|
||||||
|
* @param string $password Password
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
public function withBasicAuthentication($username, $password)
|
public function withBasicAuthentication($username, $password)
|
||||||
{
|
{
|
||||||
|
@ -102,7 +148,12 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return SoapClientBuilder
|
* Configure digest authentication.
|
||||||
|
*
|
||||||
|
* @param string $certificate Certificate
|
||||||
|
* @param string $passphrase Passphrase
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
*/
|
*/
|
||||||
public function withDigestAuthentication($certificate, $passphrase = null)
|
public function withDigestAuthentication($certificate, $passphrase = null)
|
||||||
{
|
{
|
||||||
|
@ -118,6 +169,16 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure proxy.
|
||||||
|
*
|
||||||
|
* @param string $host Host
|
||||||
|
* @param int $port Port
|
||||||
|
* @param string $username Username
|
||||||
|
* @param string $password Password
|
||||||
|
*
|
||||||
|
* @return \BeSimple\SoapClient\SoapClientBuilder
|
||||||
|
*/
|
||||||
public function withProxy($host, $port, $username = null, $password = null)
|
public function withProxy($host, $port, $username = null, $password = null)
|
||||||
{
|
{
|
||||||
$this->soapOptions['proxy_host'] = $host;
|
$this->soapOptions['proxy_host'] = $host;
|
||||||
|
@ -131,6 +192,9 @@ class SoapClientBuilder extends AbstractSoapBuilder
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate options.
|
||||||
|
*/
|
||||||
protected function validateOptions()
|
protected function validateOptions()
|
||||||
{
|
{
|
||||||
$this->validateWsdl();
|
$this->validateWsdl();
|
||||||
|
|
|
@ -12,186 +12,37 @@
|
||||||
|
|
||||||
namespace BeSimple\SoapClient;
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
|
||||||
|
use BeSimple\SoapCommon\SoapMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Francis Besset <francis.besset@gmail.com>
|
* SoapRequest class for SoapClient. Provides factory function for request object.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
*/
|
*/
|
||||||
class SoapRequest
|
class SoapRequest extends CommonSoapRequest
|
||||||
{
|
{
|
||||||
protected $function;
|
|
||||||
protected $arguments;
|
|
||||||
protected $options;
|
|
||||||
protected $headers;
|
|
||||||
|
|
||||||
public function __construct($function = null, array $arguments = array(), array $options = array(), array $headers = array())
|
|
||||||
{
|
|
||||||
$this->function = $function;
|
|
||||||
$this->arguments = $arguments;
|
|
||||||
$this->options = $options;
|
|
||||||
$this->setHeaders($headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string The function name
|
* Factory function for SoapRequest.
|
||||||
*/
|
|
||||||
public function getFunction()
|
|
||||||
{
|
|
||||||
return $this->function;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The function name
|
|
||||||
*
|
*
|
||||||
* @return SoapRequest
|
* @param string $content Content
|
||||||
*/
|
* @param string $location Location
|
||||||
public function setFunction($function)
|
* @param string $action SOAP action
|
||||||
{
|
* @param string $version SOAP version
|
||||||
$this->function = $function;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array An array with all arguments
|
|
||||||
*/
|
|
||||||
public function getArguments()
|
|
||||||
{
|
|
||||||
return $this->arguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of the argument
|
|
||||||
* @param mixed The default value returned if the argument is not exists
|
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return BeSimple\SoapClient\SoapRequest
|
||||||
*/
|
*/
|
||||||
public function getArgument($name, $default = null)
|
public static function create($content, $location, $action, $version)
|
||||||
{
|
{
|
||||||
return $this->hasArgument($name) ? $this->arguments[$name] : $default;
|
$request = new SoapRequest();
|
||||||
|
// $content is if unmodified from SoapClient not a php string type!
|
||||||
|
$request->setContent((string) $content);
|
||||||
|
$request->setLocation($location);
|
||||||
|
$request->setAction($action);
|
||||||
|
$request->setVersion($version);
|
||||||
|
$contentType = SoapMessage::getContentTypeForVersion($version);
|
||||||
|
$request->setContentType($contentType);
|
||||||
|
|
||||||
|
return $request;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of the argument
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function hasArgument($name)
|
|
||||||
{
|
|
||||||
return isset($this->arguments[$name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array An array with arguments
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function setArguments(array $arguments)
|
|
||||||
{
|
|
||||||
$this->arguments = $arguments;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of argument
|
|
||||||
* @param mixed The value of argument
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function addArgument($name, $value)
|
|
||||||
{
|
|
||||||
$this->arguments[$name] = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array An array with all options
|
|
||||||
*/
|
|
||||||
public function getOptions()
|
|
||||||
{
|
|
||||||
return $this->options;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of the option
|
|
||||||
* @param mixed The default value returned if the option is not exists
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function getOption($name, $default = null)
|
|
||||||
{
|
|
||||||
return $this->hasOption($name) ? $this->options[$name] : $default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of the option
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function hasOption($name)
|
|
||||||
{
|
|
||||||
return isset($this->options[$name]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array An array with options
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function setOptions(array $options)
|
|
||||||
{
|
|
||||||
$this->options = $options;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array|null
|
|
||||||
*/
|
|
||||||
public function getHeaders()
|
|
||||||
{
|
|
||||||
return empty($this->headers) ? null : $this->headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param array $headers
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function setHeaders(array $headers)
|
|
||||||
{
|
|
||||||
$this->headers = array();
|
|
||||||
|
|
||||||
foreach ($headers as $header) {
|
|
||||||
$this->addHeader($header);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \SoapHeader $header
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function addHeader(\SoapHeader $header)
|
|
||||||
{
|
|
||||||
$this->headers[] = $header;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string The name of option
|
|
||||||
* @param mixed The value of option
|
|
||||||
*
|
|
||||||
* @return SoapRequest
|
|
||||||
*/
|
|
||||||
public function addOption($name, $value)
|
|
||||||
{
|
|
||||||
$this->options[$name] = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
|
||||||
|
use BeSimple\SoapCommon\SoapMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SoapResponse class for SoapClient. Provides factory function for response object.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class SoapResponse extends CommonSoapResponse
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Factory function for SoapResponse.
|
||||||
|
*
|
||||||
|
* @param string $content Content
|
||||||
|
* @param string $location Location
|
||||||
|
* @param string $action SOAP action
|
||||||
|
* @param string $version SOAP version
|
||||||
|
* @param string $contentType Content type header
|
||||||
|
*
|
||||||
|
* @return BeSimple\SoapClient\SoapResponse
|
||||||
|
*/
|
||||||
|
public static function create($content, $location, $action, $version, $contentType)
|
||||||
|
{
|
||||||
|
$response = new SoapResponse();
|
||||||
|
$response->setContent($content);
|
||||||
|
$response->setLocation($location);
|
||||||
|
$response->setAction($action);
|
||||||
|
$response->setVersion($version);
|
||||||
|
$response->setContentType($contentType);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,347 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\FilterHelper;
|
||||||
|
use BeSimple\SoapCommon\Helper;
|
||||||
|
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
|
||||||
|
use BeSimple\SoapCommon\SoapRequestFilter;
|
||||||
|
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
|
||||||
|
use BeSimple\SoapCommon\SoapResponseFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This plugin implements a subset of the following standards:
|
||||||
|
* * Web Services Addressing 1.0 - Core
|
||||||
|
* http://www.w3.org/TR/2006/REC-ws-addr-core
|
||||||
|
* * Web Services Addressing 1.0 - SOAP Binding
|
||||||
|
* http://www.w3.org/TR/ws-addr-soap
|
||||||
|
*
|
||||||
|
* Per default this plugin uses the SoapClient's $action and $location values
|
||||||
|
* for wsa:Action and wsa:To. Therefore the only REQUIRED property 'wsa:Action'
|
||||||
|
* is always set automatically.
|
||||||
|
*
|
||||||
|
* Limitation: wsa:From, wsa:FaultTo and wsa:ReplyTo only support the
|
||||||
|
* wsa:Address element of the endpoint reference at the moment.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class WsAddressingFilter implements SoapRequestFilter, SoapResponseFilter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* (2.1) Endpoint reference (EPR) anonymous default address.
|
||||||
|
*
|
||||||
|
* Some endpoints cannot be located with a meaningful IRI; this URI is used
|
||||||
|
* to allow such endpoints to send and receive messages. The precise meaning
|
||||||
|
* of this URI is defined by the binding of Addressing to a specific
|
||||||
|
* protocol and/or the context in which the EPR is used.
|
||||||
|
*
|
||||||
|
* @see http://www.w3.org/TR/2006/REC-ws-addr-core-20060509/#predefaddr
|
||||||
|
*/
|
||||||
|
const ENDPOINT_REFERENCE_ANONYMOUS = 'http://www.w3.org/2005/08/addressing/anonymous';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (2.1) Endpoint reference (EPR) address for discarting messages.
|
||||||
|
*
|
||||||
|
* Messages sent to EPRs whose [address] is this value MUST be discarded
|
||||||
|
* (i.e. not sent). This URI is typically used in EPRs that designate a
|
||||||
|
* reply or fault endpoint (see section 3.1 Abstract Property Definitions)
|
||||||
|
* to indicate that no reply or fault message should be sent.
|
||||||
|
*
|
||||||
|
* @see http://www.w3.org/TR/2006/REC-ws-addr-core-20060509/#predefaddr
|
||||||
|
*/
|
||||||
|
const ENDPOINT_REFERENCE_NONE = 'http://www.w3.org/2005/08/addressing/none';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (3.1) Predefined value for reply.
|
||||||
|
*
|
||||||
|
* Indicates that this is a reply to the message identified by the [message id] IRI.
|
||||||
|
*
|
||||||
|
* see http://www.w3.org/TR/2006/REC-ws-addr-core-20060509/#predefrels
|
||||||
|
*/
|
||||||
|
const RELATIONSHIP_TYPE_REPLY = 'http://www.w3.org/2005/08/addressing/reply';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FaultTo.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $faultTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $from;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MessageId.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $messageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of reference parameters associated with this soap message.
|
||||||
|
*
|
||||||
|
* @var unknown_type
|
||||||
|
*/
|
||||||
|
protected $referenceParametersSet = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of reference parameters recieved with this soap message.
|
||||||
|
*
|
||||||
|
* @var unknown_type
|
||||||
|
*/
|
||||||
|
protected $referenceParametersRecieved = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RelatesTo.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $relatesTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RelatesTo@RelationshipType.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $relatesToRelationshipType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ReplyTo.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $replyTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add additional reference parameters
|
||||||
|
*
|
||||||
|
* @param string $ns Namespace URI
|
||||||
|
* @param string $pfx Namespace prefix
|
||||||
|
* @param string $parameter Parameter name
|
||||||
|
* @param string $value Parameter value
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addReferenceParameter($ns, $pfx, $parameter, $value)
|
||||||
|
{
|
||||||
|
$this->referenceParametersSet[] = array(
|
||||||
|
'ns' => $ns,
|
||||||
|
'pfx' => $pfx,
|
||||||
|
'parameter' => $parameter,
|
||||||
|
'value' => $value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get additional reference parameters.
|
||||||
|
*
|
||||||
|
* @param string $ns Namespace URI
|
||||||
|
* @param string $parameter Parameter name
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getReferenceParameter($ns, $parameter)
|
||||||
|
{
|
||||||
|
if (isset($this->referenceParametersRecieved[$ns][$parameter])) {
|
||||||
|
|
||||||
|
return $this->referenceParametersRecieved[$ns][$parameter];
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all properties to default values.
|
||||||
|
*/
|
||||||
|
public function resetFilter()
|
||||||
|
{
|
||||||
|
$this->faultTo = null;
|
||||||
|
$this->from = null;
|
||||||
|
$this->messageId = null;
|
||||||
|
$this->referenceParametersRecieved = array();
|
||||||
|
$this->referenceParametersSet = array();
|
||||||
|
$this->relatesTo = null;
|
||||||
|
$this->relatesToRelationshipType = null;
|
||||||
|
$this->replyTo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set FaultTo address of type xs:anyURI.
|
||||||
|
*
|
||||||
|
* @param string $faultTo xs:anyURI
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFaultTo($faultTo)
|
||||||
|
{
|
||||||
|
$this->faultTo = $faultTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set From address of type xs:anyURI.
|
||||||
|
*
|
||||||
|
* @param string $from xs:anyURI
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setFrom($from)
|
||||||
|
{
|
||||||
|
$this->from = $from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set MessageId of type xs:anyURI.
|
||||||
|
* Default: UUID v4 e.g. 'uuid:550e8400-e29b-11d4-a716-446655440000'
|
||||||
|
*
|
||||||
|
* @param string $messageId xs:anyURI
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setMessageId($messageId = null)
|
||||||
|
{
|
||||||
|
if (null === $messageId) {
|
||||||
|
$messageId = 'uuid:' . Helper::generateUUID();
|
||||||
|
}
|
||||||
|
$this->messageId = $messageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set RelatesTo of type xs:anyURI with the optional relationType
|
||||||
|
* (of type xs:anyURI).
|
||||||
|
*
|
||||||
|
* @param string $relatesTo xs:anyURI
|
||||||
|
* @param string $relationType xs:anyURI
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setRelatesTo($relatesTo, $relationType = null)
|
||||||
|
{
|
||||||
|
$this->relatesTo = $relatesTo;
|
||||||
|
if (null !== $relationType && $relationType != self::RELATIONSHIP_TYPE_REPLY) {
|
||||||
|
$this->relatesToRelationshipType = $relationType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set ReplyTo address of type xs:anyURI
|
||||||
|
* Default: self::ENDPOINT_REFERENCE_ANONYMOUS
|
||||||
|
*
|
||||||
|
* @param string $replyTo xs:anyURI
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setReplyTo($replyTo = null)
|
||||||
|
{
|
||||||
|
if (null === $replyTo) {
|
||||||
|
$replyTo = self::ENDPOINT_REFERENCE_ANONYMOUS;
|
||||||
|
}
|
||||||
|
$this->replyTo = $replyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given request XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapRequest $request SOAP request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterRequest(CommonSoapRequest $request)
|
||||||
|
{
|
||||||
|
// get \DOMDocument from SOAP request
|
||||||
|
$dom = $request->getContentDocument();
|
||||||
|
|
||||||
|
// create FilterHelper
|
||||||
|
$filterHelper = new FilterHelper($dom);
|
||||||
|
|
||||||
|
// add the neccessary namespaces
|
||||||
|
$filterHelper->addNamespace(Helper::PFX_WSA, Helper::NS_WSA);
|
||||||
|
|
||||||
|
$action = $filterHelper->createElement(Helper::NS_WSA, 'Action', $request->getAction());
|
||||||
|
$filterHelper->addHeaderElement($action);
|
||||||
|
|
||||||
|
$to = $filterHelper->createElement(Helper::NS_WSA, 'To', $request->getLocation());
|
||||||
|
$filterHelper->addHeaderElement($to);
|
||||||
|
|
||||||
|
if (null !== $this->faultTo) {
|
||||||
|
$faultTo = $filterHelper->createElement(Helper::NS_WSA, 'FaultTo');
|
||||||
|
$filterHelper->addHeaderElement($faultTo);
|
||||||
|
|
||||||
|
$address = $filterHelper->createElement(Helper::NS_WSA, 'Address', $this->faultTo);
|
||||||
|
$faultTo->appendChild($address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->from) {
|
||||||
|
$from = $filterHelper->createElement(Helper::NS_WSA, 'From');
|
||||||
|
$filterHelper->addHeaderElement($from);
|
||||||
|
|
||||||
|
$address = $filterHelper->createElement(Helper::NS_WSA, 'Address', $this->from);
|
||||||
|
$from->appendChild($address);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->messageId) {
|
||||||
|
$messageId = $filterHelper->createElement(Helper::NS_WSA, 'MessageID', $this->messageId);
|
||||||
|
$filterHelper->addHeaderElement($messageId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->relatesTo) {
|
||||||
|
$relatesTo = $filterHelper->createElement(Helper::NS_WSA, 'RelatesTo', $this->relatesTo);
|
||||||
|
if (null !== $this->relatesToRelationshipType) {
|
||||||
|
$filterHelper->setAttribute($relatesTo, Helper::NS_WSA, 'RelationshipType', $this->relatesToRelationshipType);
|
||||||
|
}
|
||||||
|
$filterHelper->addHeaderElement($relatesTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->replyTo) {
|
||||||
|
$replyTo = $filterHelper->createElement(Helper::NS_WSA, 'ReplyTo');
|
||||||
|
$filterHelper->addHeaderElement($replyTo);
|
||||||
|
|
||||||
|
$address = $filterHelper->createElement(Helper::NS_WSA, 'Address', $this->replyTo);
|
||||||
|
$replyTo->appendChild($address);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->referenceParametersSet as $rp) {
|
||||||
|
$filterHelper->addNamespace($rp['pfx'], $rp['ns']);
|
||||||
|
$parameter = $filterHelper->createElement($rp['ns'], $rp['parameter'], $rp['value']);
|
||||||
|
$filterHelper->setAttribute($parameter, Helper::NS_WSA, 'IsReferenceParameter', 'true');
|
||||||
|
$filterHelper->addHeaderElement($parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given response XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapResponse $response SOAP response
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterResponse(CommonSoapResponse $response)
|
||||||
|
{
|
||||||
|
// get \DOMDocument from SOAP response
|
||||||
|
$dom = $response->getContentDocument();
|
||||||
|
|
||||||
|
$this->referenceParametersRecieved = array();
|
||||||
|
$referenceParameters = $dom->getElementsByTagNameNS(Helper::NS_WSA, 'ReferenceParameters')->item(0);
|
||||||
|
if (null !== $referenceParameters) {
|
||||||
|
foreach ($referenceParameters->childNodes as $childNode) {
|
||||||
|
if (!isset($this->referenceParametersRecieved[$childNode->namespaceURI])) {
|
||||||
|
$this->referenceParametersRecieved[$childNode->namespaceURI] = array();
|
||||||
|
}
|
||||||
|
$this->referenceParametersRecieved[$childNode->namespaceURI][$childNode->localName] = $childNode->nodeValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,581 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use ass\XmlSecurity\DSig as XmlSecurityDSig;
|
||||||
|
use ass\XmlSecurity\Enc as XmlSecurityEnc;
|
||||||
|
use ass\XmlSecurity\Key as XmlSecurityKey;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\FilterHelper;
|
||||||
|
use BeSimple\SoapCommon\Helper;
|
||||||
|
use BeSimple\SoapCommon\SoapRequest as CommonSoapRequest;
|
||||||
|
use BeSimple\SoapCommon\SoapRequestFilter;
|
||||||
|
use BeSimple\SoapCommon\SoapResponse as CommonSoapResponse;
|
||||||
|
use BeSimple\SoapCommon\SoapResponseFilter;
|
||||||
|
use BeSimple\SoapCommon\WsSecurityKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This plugin implements a subset of the following standards:
|
||||||
|
* * Web Services Security: SOAP Message Security 1.0 (WS-Security 2004)
|
||||||
|
* http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0.pdf
|
||||||
|
* * Web Services Security UsernameToken Profile 1.0
|
||||||
|
* http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
|
||||||
|
* * Web Services Security X.509 Certificate Token Profile
|
||||||
|
* http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0.pdf
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class WsSecurityFilter implements SoapRequestFilter, SoapResponseFilter
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The date format to be used with {@link \DateTime}
|
||||||
|
*/
|
||||||
|
const DATETIME_FORMAT = 'Y-m-d\TH:i:s.000\Z';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (UT 3.1) Password type: plain text.
|
||||||
|
*/
|
||||||
|
const PASSWORD_TYPE_TEXT = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (UT 3.1) Password type: digest.
|
||||||
|
*/
|
||||||
|
const PASSWORD_TYPE_DIGEST = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (X509 3.2.1) Reference to a Subject Key Identifier
|
||||||
|
*/
|
||||||
|
const TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (X509 3.2.1) Reference to a Security Token
|
||||||
|
*/
|
||||||
|
const TOKEN_REFERENCE_SECURITY_TOKEN = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SMS_1.1 7.3) Key Identifiers
|
||||||
|
*/
|
||||||
|
const TOKEN_REFERENCE_THUMBPRINT_SHA1 = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actor.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $actor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SMS 10) Add security timestamp.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $addTimestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt the signature?
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $encryptSignature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (SMS 10) Security timestamp expires time in seconds.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $expires;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (UT 3.1) Password.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (UT 3.1) Password type: text or digest.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $passwordType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign all headers.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $signAllHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (X509 3.2) Token reference type for encryption.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $tokenReferenceEncryption = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (X509 3.2) Token reference type for signature.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $tokenReferenceSignature = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service WsSecurityKey.
|
||||||
|
*
|
||||||
|
* @var \BeSimple\SoapCommon\WsSecurityKey
|
||||||
|
*/
|
||||||
|
protected $serviceSecurityKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (UT 3.1) Username.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User WsSecurityKey.
|
||||||
|
*
|
||||||
|
* @var \BeSimple\SoapCommon\WsSecurityKey
|
||||||
|
*/
|
||||||
|
protected $userSecurityKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param boolean $addTimestamp (SMS 10) Add security timestamp.
|
||||||
|
* @param int $expires (SMS 10) Security timestamp expires time in seconds.
|
||||||
|
* @param string $actor SOAP actor
|
||||||
|
*/
|
||||||
|
public function __construct($addTimestamp = true, $expires = 300, $actor = null)
|
||||||
|
{
|
||||||
|
$this->addTimestamp = $addTimestamp;
|
||||||
|
$this->expires = $expires;
|
||||||
|
$this->actor = $actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add user data.
|
||||||
|
*
|
||||||
|
* @param string $username Username
|
||||||
|
* @param string $password Password
|
||||||
|
* @param int $passwordType self::PASSWORD_TYPE_DIGEST | self::PASSWORD_TYPE_TEXT
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addUserData($username, $password = null, $passwordType = self::PASSWORD_TYPE_DIGEST)
|
||||||
|
{
|
||||||
|
$this->username = $username;
|
||||||
|
$this->password = $password;
|
||||||
|
$this->passwordType = $passwordType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset all properties to default values.
|
||||||
|
*/
|
||||||
|
public function resetFilter()
|
||||||
|
{
|
||||||
|
$this->actor = null;
|
||||||
|
$this->addTimestamp = null;
|
||||||
|
$this->encryptSignature = null;
|
||||||
|
$this->expires = null;
|
||||||
|
$this->password = null;
|
||||||
|
$this->passwordType = null;
|
||||||
|
$this->serviceSecurityKey = null;
|
||||||
|
$this->signAllHeaders = null;
|
||||||
|
$this->tokenReferenceEncryption = null;
|
||||||
|
$this->tokenReferenceSignature = null;
|
||||||
|
$this->username = null;
|
||||||
|
$this->userSecurityKey = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get service security key.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\WsSecurityKey $serviceSecurityKey Service security key
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setServiceSecurityKeyObject(WsSecurityKey $serviceSecurityKey)
|
||||||
|
{
|
||||||
|
$this->serviceSecurityKey = $serviceSecurityKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user security key.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\WsSecurityKey $userSecurityKey User security key
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUserSecurityKeyObject(WsSecurityKey $userSecurityKey)
|
||||||
|
{
|
||||||
|
$this->userSecurityKey = $userSecurityKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set security options.
|
||||||
|
*
|
||||||
|
* @param int $tokenReference self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | self::TOKEN_REFERENCE_SECURITY_TOKEN | self::TOKEN_REFERENCE_THUMBPRINT_SHA1
|
||||||
|
* @param boolean $encryptSignature Encrypt signature
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setSecurityOptionsEncryption($tokenReference, $encryptSignature = false)
|
||||||
|
{
|
||||||
|
$this->tokenReferenceEncryption = $tokenReference;
|
||||||
|
$this->encryptSignature = $encryptSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set security options.
|
||||||
|
*
|
||||||
|
* @param int $tokenReference self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | self::TOKEN_REFERENCE_SECURITY_TOKEN | self::TOKEN_REFERENCE_THUMBPRINT_SHA1
|
||||||
|
* @param boolean $signAllHeaders Sign all headers?
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setSecurityOptionsSignature($tokenReference, $signAllHeaders = false)
|
||||||
|
{
|
||||||
|
$this->tokenReferenceSignature = $tokenReference;
|
||||||
|
$this->signAllHeaders = $signAllHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given request XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapRequest $request SOAP request
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterRequest(CommonSoapRequest $request)
|
||||||
|
{
|
||||||
|
// get \DOMDocument from SOAP request
|
||||||
|
$dom = $request->getContentDocument();
|
||||||
|
|
||||||
|
// create FilterHelper
|
||||||
|
$filterHelper = new FilterHelper($dom);
|
||||||
|
|
||||||
|
// add the neccessary namespaces
|
||||||
|
$filterHelper->addNamespace(Helper::PFX_WSS, Helper::NS_WSS);
|
||||||
|
$filterHelper->addNamespace(Helper::PFX_WSU, Helper::NS_WSU);
|
||||||
|
$filterHelper->registerNamespace(XmlSecurityDSig::PFX_XMLDSIG, XmlSecurityDSig::NS_XMLDSIG);
|
||||||
|
|
||||||
|
// init timestamp
|
||||||
|
$dt = new \DateTime('now', new \DateTimeZone('UTC'));
|
||||||
|
$createdTimestamp = $dt->format(self::DATETIME_FORMAT);
|
||||||
|
|
||||||
|
// create security header
|
||||||
|
$security = $filterHelper->createElement(Helper::NS_WSS, 'Security');
|
||||||
|
$filterHelper->addHeaderElement($security, true, $this->actor, $request->getVersion());
|
||||||
|
|
||||||
|
if (true === $this->addTimestamp || null !== $this->expires) {
|
||||||
|
$timestamp = $filterHelper->createElement(Helper::NS_WSU, 'Timestamp');
|
||||||
|
$created = $filterHelper->createElement(Helper::NS_WSU, 'Created', $createdTimestamp);
|
||||||
|
$timestamp->appendChild($created);
|
||||||
|
if (null !== $this->expires) {
|
||||||
|
$dt->modify('+' . $this->expires . ' seconds');
|
||||||
|
$expiresTimestamp = $dt->format(self::DATETIME_FORMAT);
|
||||||
|
$expires = $filterHelper->createElement(Helper::NS_WSU, 'Expires', $expiresTimestamp);
|
||||||
|
$timestamp->appendChild($expires);
|
||||||
|
}
|
||||||
|
$security->appendChild($timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->username) {
|
||||||
|
$usernameToken = $filterHelper->createElement(Helper::NS_WSS, 'UsernameToken');
|
||||||
|
$security->appendChild($usernameToken);
|
||||||
|
|
||||||
|
$username = $filterHelper->createElement(Helper::NS_WSS, 'Username', $this->username);
|
||||||
|
$usernameToken->appendChild($username);
|
||||||
|
|
||||||
|
if (null !== $this->password
|
||||||
|
&& (null === $this->userSecurityKey
|
||||||
|
|| (null !== $this->userSecurityKey && !$this->userSecurityKey->hasPrivateKey()))) {
|
||||||
|
|
||||||
|
if (self::PASSWORD_TYPE_DIGEST === $this->passwordType) {
|
||||||
|
$nonce = mt_rand();
|
||||||
|
$password = base64_encode(sha1($nonce . $createdTimestamp . $this->password, true));
|
||||||
|
$passwordType = Helper::NAME_WSS_UTP . '#PasswordDigest';
|
||||||
|
} else {
|
||||||
|
$password = $this->password;
|
||||||
|
$passwordType = Helper::NAME_WSS_UTP . '#PasswordText';
|
||||||
|
}
|
||||||
|
$password = $filterHelper->createElement(Helper::NS_WSS, 'Password', $password);
|
||||||
|
$filterHelper->setAttribute($password, null, 'Type', $passwordType);
|
||||||
|
$usernameToken->appendChild($password);
|
||||||
|
if (self::PASSWORD_TYPE_DIGEST === $this->passwordType) {
|
||||||
|
$nonce = $filterHelper->createElement(Helper::NS_WSS, 'Nonce', base64_encode($nonce));
|
||||||
|
$usernameToken->appendChild($nonce);
|
||||||
|
|
||||||
|
$created = $filterHelper->createElement(Helper::NS_WSU, 'Created', $createdTimestamp);
|
||||||
|
$usernameToken->appendChild($created);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->userSecurityKey && $this->userSecurityKey->hasKeys()) {
|
||||||
|
$guid = 'CertId-' . Helper::generateUUID();
|
||||||
|
// add token references
|
||||||
|
$keyInfo = null;
|
||||||
|
if (null !== $this->tokenReferenceSignature) {
|
||||||
|
$keyInfo = $this->createKeyInfo($filterHelper, $this->tokenReferenceSignature, $guid, $this->userSecurityKey->getPublicKey());
|
||||||
|
}
|
||||||
|
$nodes = $this->createNodeListForSigning($dom, $security);
|
||||||
|
$signature = XmlSecurityDSig::createSignature($this->userSecurityKey->getPrivateKey(), XmlSecurityDSig::EXC_C14N, $security, null, $keyInfo);
|
||||||
|
$options = array(
|
||||||
|
'id_ns_prefix' => Helper::PFX_WSU,
|
||||||
|
'id_prefix_ns' => Helper::NS_WSU,
|
||||||
|
);
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
XmlSecurityDSig::addNodeToSignature($signature, $node, XmlSecurityDSig::SHA1, XmlSecurityDSig::EXC_C14N, $options);
|
||||||
|
}
|
||||||
|
XmlSecurityDSig::signDocument($signature, $this->userSecurityKey->getPrivateKey(), XmlSecurityDSig::EXC_C14N);
|
||||||
|
|
||||||
|
$publicCertificate = $this->userSecurityKey->getPublicKey()->getX509Certificate(true);
|
||||||
|
$binarySecurityToken = $filterHelper->createElement(Helper::NS_WSS, 'BinarySecurityToken', $publicCertificate);
|
||||||
|
$filterHelper->setAttribute($binarySecurityToken, null, 'EncodingType', Helper::NAME_WSS_SMS . '#Base64Binary');
|
||||||
|
$filterHelper->setAttribute($binarySecurityToken, null, 'ValueType', Helper::NAME_WSS_X509 . '#X509v3');
|
||||||
|
$filterHelper->setAttribute($binarySecurityToken, Helper::NS_WSU, 'Id', $guid);
|
||||||
|
$security->insertBefore($binarySecurityToken, $signature);
|
||||||
|
|
||||||
|
// encrypt soap document
|
||||||
|
if (null !== $this->serviceSecurityKey && $this->serviceSecurityKey->hasKeys()) {
|
||||||
|
$guid = 'EncKey-' . Helper::generateUUID();
|
||||||
|
// add token references
|
||||||
|
$keyInfo = null;
|
||||||
|
if (null !== $this->tokenReferenceEncryption) {
|
||||||
|
$keyInfo = $this->createKeyInfo($filterHelper, $this->tokenReferenceEncryption, $guid, $this->serviceSecurityKey->getPublicKey());
|
||||||
|
}
|
||||||
|
$encryptedKey = XmlSecurityEnc::createEncryptedKey($guid, $this->serviceSecurityKey->getPrivateKey(), $this->serviceSecurityKey->getPublicKey(), $security, $signature, $keyInfo);
|
||||||
|
$referenceList = XmlSecurityEnc::createReferenceList($encryptedKey);
|
||||||
|
// token reference to encrypted key
|
||||||
|
$keyInfo = $this->createKeyInfo($filterHelper, self::TOKEN_REFERENCE_SECURITY_TOKEN, $guid);
|
||||||
|
$nodes = $this->createNodeListForEncryption($dom, $security);
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$type = XmlSecurityEnc::ELEMENT;
|
||||||
|
if ($node->localName == 'Body') {
|
||||||
|
$type = XmlSecurityEnc::CONTENT;
|
||||||
|
}
|
||||||
|
XmlSecurityEnc::encryptNode($node, $type, $this->serviceSecurityKey->getPrivateKey(), $referenceList, $keyInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modify the given request XML.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapCommon\SoapResponse $response SOAP response
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function filterResponse(CommonSoapResponse $response)
|
||||||
|
{
|
||||||
|
// get \DOMDocument from SOAP response
|
||||||
|
$dom = $response->getContentDocument();
|
||||||
|
|
||||||
|
// locate security header
|
||||||
|
$security = $dom->getElementsByTagNameNS(Helper::NS_WSS, 'Security')->item(0);
|
||||||
|
if (null !== $security) {
|
||||||
|
// add SecurityTokenReference resolver for KeyInfo
|
||||||
|
if (null !== $this->serviceSecurityKey) {
|
||||||
|
$keyResolver = array($this, 'keyInfoSecurityTokenReferenceResolver');
|
||||||
|
XmlSecurityDSig::addKeyInfoResolver(Helper::NS_WSS, 'SecurityTokenReference', $keyResolver);
|
||||||
|
}
|
||||||
|
// do we have a reference list in header
|
||||||
|
$referenceList = XmlSecurityEnc::locateReferenceList($security);
|
||||||
|
// get a list of encrypted nodes
|
||||||
|
$encryptedNodes = XmlSecurityEnc::locateEncryptedData($dom, $referenceList);
|
||||||
|
// decrypt them
|
||||||
|
if (null !== $encryptedNodes) {
|
||||||
|
foreach ($encryptedNodes as $encryptedNode) {
|
||||||
|
XmlSecurityEnc::decryptNode($encryptedNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// locate signature node
|
||||||
|
$signature = XmlSecurityDSig::locateSignature($security);
|
||||||
|
if (null !== $signature) {
|
||||||
|
// verify references
|
||||||
|
$options = array(
|
||||||
|
'id_ns_prefix' => Helper::PFX_WSU,
|
||||||
|
'id_prefix_ns' => Helper::NS_WSU,
|
||||||
|
);
|
||||||
|
if (XmlSecurityDSig::verifyReferences($signature, $options) !== true) {
|
||||||
|
throw new \SoapFault('wsse:FailedCheck', 'The signature or decryption was invalid');
|
||||||
|
}
|
||||||
|
// verify signature
|
||||||
|
if (XmlSecurityDSig::verifyDocumentSignature($signature) !== true) {
|
||||||
|
throw new \SoapFault('wsse:FailedCheck', 'The signature or decryption was invalid');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the configured KeyInfo to the parentNode.
|
||||||
|
*
|
||||||
|
* @param FilterHelper $filterHelper Filter helper object
|
||||||
|
* @param int $tokenReference Token reference type
|
||||||
|
* @param string $guid Unique ID
|
||||||
|
* @param \ass\XmlSecurity\Key $xmlSecurityKey XML security key
|
||||||
|
*
|
||||||
|
* @return \DOMElement
|
||||||
|
*/
|
||||||
|
protected function createKeyInfo(FilterHelper $filterHelper, $tokenReference, $guid, XmlSecurityKey $xmlSecurityKey = null)
|
||||||
|
{
|
||||||
|
$keyInfo = $filterHelper->createElement(XmlSecurityDSig::NS_XMLDSIG, 'KeyInfo');
|
||||||
|
$securityTokenReference = $filterHelper->createElement(Helper::NS_WSS, 'SecurityTokenReference');
|
||||||
|
$keyInfo->appendChild($securityTokenReference);
|
||||||
|
// security token
|
||||||
|
if (self::TOKEN_REFERENCE_SECURITY_TOKEN === $tokenReference) {
|
||||||
|
$reference = $filterHelper->createElement(Helper::NS_WSS, 'Reference');
|
||||||
|
$filterHelper->setAttribute($reference, null, 'URI', '#' . $guid);
|
||||||
|
if (null !== $xmlSecurityKey) {
|
||||||
|
$filterHelper->setAttribute($reference, null, 'ValueType', Helper::NAME_WSS_X509 . '#X509v3');
|
||||||
|
}
|
||||||
|
$securityTokenReference->appendChild($reference);
|
||||||
|
// subject key identifier
|
||||||
|
} elseif (self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER === $tokenReference && null !== $xmlSecurityKey) {
|
||||||
|
$keyIdentifier = $filterHelper->createElement(Helper::NS_WSS, 'KeyIdentifier');
|
||||||
|
$filterHelper->setAttribute($keyIdentifier, null, 'EncodingType', Helper::NAME_WSS_SMS . '#Base64Binary');
|
||||||
|
$filterHelper->setAttribute($keyIdentifier, null, 'ValueType', Helper::NAME_WSS_X509 . '#509SubjectKeyIdentifier');
|
||||||
|
$securityTokenReference->appendChild($keyIdentifier);
|
||||||
|
$certificate = $xmlSecurityKey->getX509SubjectKeyIdentifier();
|
||||||
|
$dataNode = new \DOMText($certificate);
|
||||||
|
$keyIdentifier->appendChild($dataNode);
|
||||||
|
// thumbprint sha1
|
||||||
|
} elseif (self::TOKEN_REFERENCE_THUMBPRINT_SHA1 === $tokenReference && null !== $xmlSecurityKey) {
|
||||||
|
$keyIdentifier = $filterHelper->createElement(Helper::NS_WSS, 'KeyIdentifier');
|
||||||
|
$filterHelper->setAttribute($keyIdentifier, null, 'EncodingType', Helper::NAME_WSS_SMS . '#Base64Binary');
|
||||||
|
$filterHelper->setAttribute($keyIdentifier, null, 'ValueType', Helper::NAME_WSS_SMS_1_1 . '#ThumbprintSHA1');
|
||||||
|
$securityTokenReference->appendChild($keyIdentifier);
|
||||||
|
$thumbprintSha1 = base64_encode(sha1(base64_decode($xmlSecurityKey->getX509Certificate(true)), true));
|
||||||
|
$dataNode = new \DOMText($thumbprintSha1);
|
||||||
|
$keyIdentifier->appendChild($dataNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $keyInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of \DOMNodes that should be encrypted.
|
||||||
|
*
|
||||||
|
* @param \DOMDocument $dom DOMDocument to query
|
||||||
|
* @param \DOMElement $security Security element
|
||||||
|
*
|
||||||
|
* @return \DOMNodeList
|
||||||
|
*/
|
||||||
|
protected function createNodeListForEncryption(\DOMDocument $dom, \DOMElement $security)
|
||||||
|
{
|
||||||
|
$xpath = new \DOMXPath($dom);
|
||||||
|
$xpath->registerNamespace('SOAP-ENV', $dom->documentElement->namespaceURI);
|
||||||
|
$xpath->registerNamespace('ds', XmlSecurityDSig::NS_XMLDSIG);
|
||||||
|
if ($this->encryptSignature === true) {
|
||||||
|
$query = '//ds:Signature | //SOAP-ENV:Body';
|
||||||
|
} else {
|
||||||
|
$query = '//SOAP-ENV:Body';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $xpath->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a list of \DOMNodes that should be signed.
|
||||||
|
*
|
||||||
|
* @param \DOMDocument $dom DOMDocument to query
|
||||||
|
* @param \DOMElement $security Security element
|
||||||
|
*
|
||||||
|
* @return array(\DOMNode)
|
||||||
|
*/
|
||||||
|
protected function createNodeListForSigning(\DOMDocument $dom, \DOMElement $security)
|
||||||
|
{
|
||||||
|
$nodes = array();
|
||||||
|
$body = $dom->getElementsByTagNameNS($dom->documentElement->namespaceURI, 'Body')->item(0);
|
||||||
|
if (null !== $body) {
|
||||||
|
$nodes[] = $body;
|
||||||
|
}
|
||||||
|
foreach ($security->childNodes as $node) {
|
||||||
|
if (XML_ELEMENT_NODE === $node->nodeType) {
|
||||||
|
$nodes[] = $node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->signAllHeaders) {
|
||||||
|
foreach ($security->parentNode->childNodes as $node) {
|
||||||
|
if (XML_ELEMENT_NODE === $node->nodeType &&
|
||||||
|
Helper::NS_WSS !== $node->namespaceURI) {
|
||||||
|
$nodes[] = $node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the referenced node for the given URI.
|
||||||
|
*
|
||||||
|
* @param \DOMElement $node Node
|
||||||
|
* @param string $uri URI
|
||||||
|
*
|
||||||
|
* @return \DOMElement
|
||||||
|
*/
|
||||||
|
protected function getReferenceNodeForUri(\DOMElement $node, $uri)
|
||||||
|
{
|
||||||
|
$url = parse_url($uri);
|
||||||
|
$referenceId = $url['fragment'];
|
||||||
|
$query = '//*[@'.Helper::PFX_WSU.':Id="'.$referenceId.'" or @Id="'.$referenceId.'"]';
|
||||||
|
$xpath = new \DOMXPath($node->ownerDocument);
|
||||||
|
$xpath->registerNamespace(Helper::PFX_WSU, Helper::NS_WSU);
|
||||||
|
|
||||||
|
return $xpath->query($query)->item(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to resolve a key from the given \DOMElement.
|
||||||
|
*
|
||||||
|
* @param \DOMElement $node Node where to resolve the key
|
||||||
|
* @param string $algorithm XML security key algorithm
|
||||||
|
*
|
||||||
|
* @return \ass\XmlSecurity\Key|null
|
||||||
|
*/
|
||||||
|
public function keyInfoSecurityTokenReferenceResolver(\DOMElement $node, $algorithm)
|
||||||
|
{
|
||||||
|
foreach ($node->childNodes as $key) {
|
||||||
|
if (Helper::NS_WSS === $key->namespaceURI) {
|
||||||
|
switch ($key->localName) {
|
||||||
|
case 'KeyIdentifier':
|
||||||
|
|
||||||
|
return $this->serviceSecurityKey->getPublicKey();
|
||||||
|
case 'Reference':
|
||||||
|
$uri = $key->getAttribute('URI');
|
||||||
|
$referencedNode = $this->getReferenceNodeForUri($node, $uri);
|
||||||
|
|
||||||
|
if (XmlSecurityEnc::NS_XMLENC === $referencedNode->namespaceURI
|
||||||
|
&& 'EncryptedKey' == $referencedNode->localName) {
|
||||||
|
$key = XmlSecurityEnc::decryptEncryptedKey($referencedNode, $this->userSecurityKey->getPrivateKey());
|
||||||
|
|
||||||
|
return XmlSecurityKey::factory($algorithm, $key, XmlSecurityKey::TYPE_PRIVATE);
|
||||||
|
} else {
|
||||||
|
//$valueType = $key->getAttribute('ValueType');
|
||||||
|
|
||||||
|
return $this->serviceSecurityKey->getPublicKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads WSDL files with cURL. Uses the WSDL_CACHE_* constants and the
|
||||||
|
* 'soap.wsdl_*' ini settings. Does only file caching as SoapClient only
|
||||||
|
* supports a file name parameter. The class also resolves remote XML schema
|
||||||
|
* includes.
|
||||||
|
*
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class WsdlDownloader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Cache enabled.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $cacheEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache dir.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $cacheDir;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache TTL.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $cacheTtl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cURL instance for downloads.
|
||||||
|
*
|
||||||
|
* @var unknown_type
|
||||||
|
*/
|
||||||
|
protected $curl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve WSDl/XSD includes.
|
||||||
|
*
|
||||||
|
* @var boolean
|
||||||
|
*/
|
||||||
|
protected $resolveRemoteIncludes = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param \BeSimple\SoapClient\Curl $curl Curl instance
|
||||||
|
* @param boolean $resolveRemoteIncludes WSDL/XSD include enabled?
|
||||||
|
* @param boolean $cacheWsdl Cache constant
|
||||||
|
*/
|
||||||
|
public function __construct(Curl $curl, $resolveRemoteIncludes = true, $cacheWsdl = WSDL_CACHE_DISK)
|
||||||
|
{
|
||||||
|
$this->curl = $curl;
|
||||||
|
$this->resolveRemoteIncludes = $resolveRemoteIncludes;
|
||||||
|
// get current WSDL caching config
|
||||||
|
$this->cacheEnabled = (bool) ini_get('soap.wsdl_cache_enabled');
|
||||||
|
if ($this->cacheEnabled === true
|
||||||
|
&& $cacheWsdl === WSDL_CACHE_NONE) {
|
||||||
|
$this->cacheEnabled = false;
|
||||||
|
}
|
||||||
|
$this->cacheDir = ini_get('soap.wsdl_cache_dir');
|
||||||
|
if (!is_dir($this->cacheDir)) {
|
||||||
|
$this->cacheDir = sys_get_temp_dir();
|
||||||
|
}
|
||||||
|
$this->cacheDir = rtrim($this->cacheDir, '/\\');
|
||||||
|
$this->cacheTtl = ini_get('soap.wsdl_cache_ttl');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download given WSDL file and return name of cache file.
|
||||||
|
*
|
||||||
|
* @param string $wsdl WSDL file URL/path
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function download($wsdl)
|
||||||
|
{
|
||||||
|
// download and cache remote WSDL files or local ones where we want to
|
||||||
|
// resolve remote XSD includes
|
||||||
|
$isRemoteFile = $this->isRemoteFile($wsdl);
|
||||||
|
if ($isRemoteFile === true || $this->resolveRemoteIncludes === true) {
|
||||||
|
$cacheFile = $this->cacheDir . DIRECTORY_SEPARATOR . 'wsdl_' . md5($wsdl) . '.cache';
|
||||||
|
if ($this->cacheEnabled === false
|
||||||
|
|| !file_exists($cacheFile)
|
||||||
|
|| (filemtime($cacheFile) + $this->cacheTtl) < time()) {
|
||||||
|
if ($isRemoteFile === true) {
|
||||||
|
// execute request
|
||||||
|
$responseSuccessfull = $this->curl->exec($wsdl);
|
||||||
|
// get content
|
||||||
|
if ($responseSuccessfull === true) {
|
||||||
|
$response = $this->curl->getResponseBody();
|
||||||
|
if ($this->resolveRemoteIncludes === true) {
|
||||||
|
$this->resolveRemoteIncludes($response, $cacheFile, $wsdl);
|
||||||
|
} else {
|
||||||
|
file_put_contents($cacheFile, $response);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'");
|
||||||
|
}
|
||||||
|
} elseif (file_exists($wsdl)) {
|
||||||
|
$response = file_get_contents($wsdl);
|
||||||
|
$this->resolveRemoteIncludes($response, $cacheFile);
|
||||||
|
} else {
|
||||||
|
throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cacheFile;
|
||||||
|
} elseif (file_exists($wsdl)) {
|
||||||
|
|
||||||
|
return realpath($wsdl);
|
||||||
|
} else {
|
||||||
|
throw new \ErrorException("SOAP-ERROR: Parsing WSDL: Couldn't load from '" . $wsdl ."'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we have a remote file?
|
||||||
|
*
|
||||||
|
* @param string $file File URL/path
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
private function isRemoteFile($file)
|
||||||
|
{
|
||||||
|
$isRemoteFile = false;
|
||||||
|
// @parse_url to suppress E_WARNING for invalid urls
|
||||||
|
if (($url = @parse_url($file)) !== false) {
|
||||||
|
if (isset($url['scheme']) && substr($url['scheme'], 0, 4) == 'http') {
|
||||||
|
$isRemoteFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $isRemoteFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves remote WSDL/XSD includes within the WSDL files.
|
||||||
|
*
|
||||||
|
* @param string $xml XML file
|
||||||
|
* @param string $cacheFile Cache file name
|
||||||
|
* @param boolean $parentFile Parent file name
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function resolveRemoteIncludes($xml, $cacheFile, $parentFile = null)
|
||||||
|
{
|
||||||
|
$doc = new \DOMDocument();
|
||||||
|
$doc->loadXML($xml);
|
||||||
|
$xpath = new \DOMXPath($doc);
|
||||||
|
$xpath->registerNamespace(Helper::PFX_XML_SCHEMA, Helper::NS_XML_SCHEMA);
|
||||||
|
$xpath->registerNamespace(Helper::PFX_WSDL, Helper::NS_WSDL);
|
||||||
|
// WSDL include/import
|
||||||
|
$query = './/' . Helper::PFX_WSDL . ':include | .//' . Helper::PFX_WSDL . ':import';
|
||||||
|
$nodes = $xpath->query($query);
|
||||||
|
if ($nodes->length > 0) {
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$location = $node->getAttribute('location');
|
||||||
|
if ($this->isRemoteFile($location)) {
|
||||||
|
$location = $this->download($location);
|
||||||
|
$node->setAttribute('location', $location);
|
||||||
|
} elseif (!is_null($parentFile)) {
|
||||||
|
$location = $this->resolveRelativePathInUrl($parentFile, $location);
|
||||||
|
$location = $this->download($location);
|
||||||
|
$node->setAttribute('location', $location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// XML schema include/import
|
||||||
|
$query = './/' . Helper::PFX_XML_SCHEMA . ':include | .//' . Helper::PFX_XML_SCHEMA . ':import';
|
||||||
|
$nodes = $xpath->query($query);
|
||||||
|
if ($nodes->length > 0) {
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
$schemaLocation = $node->getAttribute('schemaLocation');
|
||||||
|
if ($this->isRemoteFile($schemaLocation)) {
|
||||||
|
$schemaLocation = $this->download($schemaLocation);
|
||||||
|
$node->setAttribute('schemaLocation', $schemaLocation);
|
||||||
|
} elseif (!is_null($parentFile)) {
|
||||||
|
$schemaLocation = $this->resolveRelativePathInUrl($parentFile, $schemaLocation);
|
||||||
|
$schemaLocation = $this->download($schemaLocation);
|
||||||
|
$node->setAttribute('schemaLocation', $schemaLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$doc->save($cacheFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the relative path to base into an absolute.
|
||||||
|
*
|
||||||
|
* @param string $base Base path
|
||||||
|
* @param string $relative Relative path
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function resolveRelativePathInUrl($base, $relative)
|
||||||
|
{
|
||||||
|
$urlParts = parse_url($base);
|
||||||
|
// combine base path with relative path
|
||||||
|
if (isset($urlParts['path']) && strpos($relative, '/') === 0) {
|
||||||
|
// $relative is absolute path from domain (starts with /)
|
||||||
|
$path = $relative;
|
||||||
|
} elseif (isset($urlParts['path']) && strrpos($urlParts['path'], '/') === (strlen($urlParts['path']) )) {
|
||||||
|
// base path is directory
|
||||||
|
$path = $urlParts['path'] . $relative;
|
||||||
|
} elseif (isset($urlParts['path'])) {
|
||||||
|
// strip filename from base path
|
||||||
|
$path = substr($urlParts['path'], 0, strrpos($urlParts['path'], '/')) . '/' . $relative;
|
||||||
|
} else {
|
||||||
|
// no base path
|
||||||
|
$path = '/' . $relative;
|
||||||
|
}
|
||||||
|
// foo/./bar ==> foo/bar
|
||||||
|
$path = preg_replace('~/\./~', '/', $path);
|
||||||
|
// remove double slashes
|
||||||
|
$path = preg_replace('~/+~', '/', $path);
|
||||||
|
// split path by '/'
|
||||||
|
$parts = explode('/', $path);
|
||||||
|
// resolve /../
|
||||||
|
foreach ($parts as $key => $part) {
|
||||||
|
if ($part == "..") {
|
||||||
|
$keyToDelete = $key-1;
|
||||||
|
while ($keyToDelete > 0) {
|
||||||
|
if (isset($parts[$keyToDelete])) {
|
||||||
|
unset($parts[$keyToDelete]);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$keyToDelete--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($parts[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$hostname = $urlParts['scheme'] . '://' . $urlParts['host'];
|
||||||
|
if (isset($urlParts['port'])) {
|
||||||
|
$hostname .= ':' . $urlParts['port'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $hostname . implode('/', $parts);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\Helper as BeSimpleSoapHelper;
|
||||||
|
use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient;
|
||||||
|
|
||||||
|
require '../bootstrap.php';
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'soap_version' => SOAP_1_1,
|
||||||
|
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
|
||||||
|
'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders
|
||||||
|
'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_MTOM,
|
||||||
|
'cache_wsdl' => WSDL_CACHE_NONE,
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deploy "axis_services/sample-mtom.aar" to Apache Axis2 to get this
|
||||||
|
* example to work.
|
||||||
|
*
|
||||||
|
* Apache Axis2 MTOM example.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$sc = new BeSimpleSoapClient('MTOM.wsdl', $options);
|
||||||
|
|
||||||
|
//var_dump($sc->__getFunctions());
|
||||||
|
//var_dump($sc->__getTypes());
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$attachment = new stdClass();
|
||||||
|
$attachment->fileName = 'test123.txt';
|
||||||
|
$attachment->binaryData = 'This is a test.';
|
||||||
|
|
||||||
|
var_dump($sc->attachment($attachment));
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// var_dump(
|
||||||
|
// $sc->__getLastRequestHeaders(),
|
||||||
|
// $sc->__getLastRequest(),
|
||||||
|
// $sc->__getLastResponseHeaders(),
|
||||||
|
// $sc->__getLastResponse()
|
||||||
|
// );
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<definitions targetNamespace="http://ws.apache.org/axis2/mtomsample/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://ws.apache.org/axis2/mtomsample/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/">
|
||||||
|
<types>
|
||||||
|
<xsd:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://ws.apache.org/axis2/mtomsample/" xmlns="http://schemas.xmlsoap.org/wsdl/">
|
||||||
|
<xsd:import namespace="http://www.w3.org/2005/05/xmlmime"/>
|
||||||
|
<xsd:complexType name="AttachmentType">
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element minOccurs="0" name="fileName" type="xsd:string"/>
|
||||||
|
<xsd:element minOccurs="0" name="binaryData" type="xmime:base64Binary"/>
|
||||||
|
</xsd:sequence>
|
||||||
|
</xsd:complexType>
|
||||||
|
<xsd:element name="AttachmentRequest" type="tns:AttachmentType"/>
|
||||||
|
<xsd:element name="AttachmentResponse" type="xsd:string"/>
|
||||||
|
</xsd:schema>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://www.w3.org/2005/05/xmlmime">
|
||||||
|
<xs:attribute name="contentType">
|
||||||
|
<xs:simpleType>
|
||||||
|
<xs:restriction base="xs:string">
|
||||||
|
<xs:minLength value="3"/>
|
||||||
|
</xs:restriction>
|
||||||
|
</xs:simpleType>
|
||||||
|
</xs:attribute>
|
||||||
|
<xs:attribute name="expectedContentTypes" type="xs:string"/>
|
||||||
|
<xs:complexType name="base64Binary">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="xs:base64Binary">
|
||||||
|
<xs:attribute ref="xmime:contentType"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:complexType name="hexBinary">
|
||||||
|
<xs:simpleContent>
|
||||||
|
<xs:extension base="xs:hexBinary">
|
||||||
|
<xs:attribute ref="xmime:contentType"/>
|
||||||
|
</xs:extension>
|
||||||
|
</xs:simpleContent>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:schema>
|
||||||
|
|
||||||
|
</types>
|
||||||
|
<message name="AttachmentResponse">
|
||||||
|
<part name="part1" element="tns:AttachmentResponse">
|
||||||
|
</part>
|
||||||
|
</message>
|
||||||
|
<message name="AttachmentRequest">
|
||||||
|
<part name="part1" element="tns:AttachmentRequest">
|
||||||
|
</part>
|
||||||
|
</message>
|
||||||
|
<portType name="MTOMServicePortType">
|
||||||
|
<operation name="attachment">
|
||||||
|
<input message="tns:AttachmentRequest" wsaw:Action="attachment">
|
||||||
|
</input>
|
||||||
|
<output message="tns:AttachmentResponse" wsaw:Action="http://schemas.xmlsoap.org/wsdl/MTOMServicePortType/AttachmentResponse">
|
||||||
|
</output>
|
||||||
|
</operation>
|
||||||
|
</portType>
|
||||||
|
<binding name="MTOMServiceSOAP11Binding" type="tns:MTOMServicePortType">
|
||||||
|
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
||||||
|
<operation name="attachment">
|
||||||
|
<soap:operation soapAction="attachment" style="document"/>
|
||||||
|
<input>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</input>
|
||||||
|
<output>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</output>
|
||||||
|
</operation>
|
||||||
|
</binding>
|
||||||
|
<binding name="MTOMServiceSOAP12Binding" type="tns:MTOMServicePortType">
|
||||||
|
<soap12:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
||||||
|
<operation name="attachment">
|
||||||
|
<soap12:operation soapAction="attachment" style="document"/>
|
||||||
|
<input>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</input>
|
||||||
|
<output>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</output>
|
||||||
|
</operation>
|
||||||
|
</binding>
|
||||||
|
<service name="MTOMSample">
|
||||||
|
<port name="MTOMSampleSOAP12port_http" binding="tns:MTOMServiceSOAP12Binding">
|
||||||
|
<soap12:address location="http://192.168.0.104:8080/axis2/services/MTOMSample.MTOMSampleSOAP12port_http/"/>
|
||||||
|
</port>
|
||||||
|
<port name="MTOMSampleSOAP11port_http" binding="tns:MTOMServiceSOAP11Binding">
|
||||||
|
<soap:address location="http://192.168.0.104:8080/axis2/services/MTOMSample.MTOMSampleSOAP11port_http/"/>
|
||||||
|
</port>
|
||||||
|
</service>
|
||||||
|
</definitions>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use BeSimple\SoapCommon\Helper as BeSimpleSoapHelper;
|
||||||
|
use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient;
|
||||||
|
|
||||||
|
require '../bootstrap.php';
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'soap_version' => SOAP_1_1,
|
||||||
|
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
|
||||||
|
'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders
|
||||||
|
'attachment_type' => BeSimpleSoapHelper::ATTACHMENTS_TYPE_SWA,
|
||||||
|
'cache_wsdl' => WSDL_CACHE_NONE,
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deploy "axis_services/besimple-swa.aar" to Apache Axis2 to get this
|
||||||
|
* example to work.
|
||||||
|
*
|
||||||
|
* Run ant to rebuild aar.
|
||||||
|
*
|
||||||
|
* Example based on:
|
||||||
|
* http://axis.apache.org/axis2/java/core/docs/mtom-guide.html#a3
|
||||||
|
* http://wso2.org/library/1675
|
||||||
|
*
|
||||||
|
* Doesn't work directly with ?wsdl served by Apache Axis!
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
$sc = new BeSimpleSoapClient('SwA.wsdl', $options);
|
||||||
|
|
||||||
|
//var_dump($sc->__getFunctions());
|
||||||
|
//var_dump($sc->__getTypes());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$file = new stdClass();
|
||||||
|
$file->name = 'upload.txt';
|
||||||
|
$file->data = 'This is a test text!';
|
||||||
|
$result = $sc->uploadFile($file);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$result->return
|
||||||
|
);
|
||||||
|
|
||||||
|
$file = new stdClass();
|
||||||
|
$file->name = 'upload.txt';
|
||||||
|
$result = $sc->downloadFile($file);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$result->data
|
||||||
|
);
|
||||||
|
|
||||||
|
$file = new stdClass();
|
||||||
|
$file->name = 'image.jpg'; // source: http://www.freeimageslive.com/galleries/light/pics/swirl3768.jpg
|
||||||
|
$file->data = file_get_contents('image.jpg');
|
||||||
|
$result = $sc->uploadFile($file);
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
$result->return
|
||||||
|
);
|
||||||
|
|
||||||
|
$crc32 = crc32($file->data);
|
||||||
|
|
||||||
|
$file = new stdClass();
|
||||||
|
$file->name = 'image.jpg';
|
||||||
|
$result = $sc->downloadFile($file);
|
||||||
|
|
||||||
|
file_put_contents('image2.jpg', $result->data);
|
||||||
|
|
||||||
|
|
||||||
|
var_dump(
|
||||||
|
crc32($result->data) === $crc32
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// var_dump(
|
||||||
|
// $sc->__getLastRequestHeaders(),
|
||||||
|
// $sc->__getLastRequest(),
|
||||||
|
// $sc->__getLastResponseHeaders(),
|
||||||
|
// $sc->__getLastResponse()
|
||||||
|
// );
|
|
@ -0,0 +1,162 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://service.besimple" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://service.besimple">
|
||||||
|
<wsdl:documentation>BeSimpleSwaService</wsdl:documentation>
|
||||||
|
<wsdl:types>
|
||||||
|
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://service.besimple">
|
||||||
|
<xs:complexType name="Exception">
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="Exception" nillable="true" type="xs:anyType"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
<xs:element name="Exception">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="Exception" nillable="true" type="ns:Exception"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="uploadFile">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="data" nillable="true" type="xs:base64Binary"/>
|
||||||
|
<xs:element minOccurs="0" name="name" nillable="true" type="xs:string"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="uploadFileResponse">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="downloadFile">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="name" nillable="true" type="xs:string"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
<xs:element name="downloadFileResponse">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element minOccurs="0" name="data" nillable="true" type="xs:base64Binary"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
</wsdl:types>
|
||||||
|
<wsdl:message name="downloadFileRequest">
|
||||||
|
<wsdl:part name="parameters" element="ns:downloadFile"/>
|
||||||
|
</wsdl:message>
|
||||||
|
<wsdl:message name="downloadFileResponse">
|
||||||
|
<wsdl:part name="parameters" element="ns:downloadFileResponse"/>
|
||||||
|
</wsdl:message>
|
||||||
|
<wsdl:message name="Exception">
|
||||||
|
<wsdl:part name="parameters" element="ns:Exception"/>
|
||||||
|
</wsdl:message>
|
||||||
|
<wsdl:message name="uploadFileRequest">
|
||||||
|
<wsdl:part name="parameters" element="ns:uploadFile"/>
|
||||||
|
</wsdl:message>
|
||||||
|
<wsdl:message name="uploadFileResponse">
|
||||||
|
<wsdl:part name="parameters" element="ns:uploadFileResponse"/>
|
||||||
|
</wsdl:message>
|
||||||
|
<wsdl:portType name="BeSimpleSwaServicePortType">
|
||||||
|
<wsdl:operation name="downloadFile">
|
||||||
|
<wsdl:input message="ns:downloadFileRequest" wsaw:Action="urn:downloadFile"/>
|
||||||
|
<wsdl:output message="ns:downloadFileResponse" wsaw:Action="urn:downloadFileResponse"/>
|
||||||
|
<wsdl:fault message="ns:Exception" name="Exception" wsaw:Action="urn:downloadFileException"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
<wsdl:operation name="uploadFile">
|
||||||
|
<wsdl:input message="ns:uploadFileRequest" wsaw:Action="urn:uploadFile"/>
|
||||||
|
<wsdl:output message="ns:uploadFileResponse" wsaw:Action="urn:uploadFileResponse"/>
|
||||||
|
<wsdl:fault message="ns:Exception" name="Exception" wsaw:Action="urn:uploadFileException"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
</wsdl:portType>
|
||||||
|
<wsdl:binding name="BeSimpleSwaServiceSoap11Binding" type="ns:BeSimpleSwaServicePortType">
|
||||||
|
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
|
||||||
|
<wsdl:operation name="downloadFile">
|
||||||
|
<soap:operation soapAction="urn:downloadFile" style="document"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
<wsdl:fault name="Exception">
|
||||||
|
<soap:fault use="literal" name="Exception"/>
|
||||||
|
</wsdl:fault>
|
||||||
|
</wsdl:operation>
|
||||||
|
<wsdl:operation name="uploadFile">
|
||||||
|
<soap:operation soapAction="urn:uploadFile" style="document"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<soap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
<wsdl:fault name="Exception">
|
||||||
|
<soap:fault use="literal" name="Exception"/>
|
||||||
|
</wsdl:fault>
|
||||||
|
</wsdl:operation>
|
||||||
|
</wsdl:binding>
|
||||||
|
<wsdl:binding name="BeSimpleSwaServiceSoap12Binding" type="ns:BeSimpleSwaServicePortType">
|
||||||
|
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
|
||||||
|
<wsdl:operation name="downloadFile">
|
||||||
|
<soap12:operation soapAction="urn:downloadFile" style="document"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
<wsdl:fault name="Exception">
|
||||||
|
<soap12:fault use="literal" name="Exception"/>
|
||||||
|
</wsdl:fault>
|
||||||
|
</wsdl:operation>
|
||||||
|
<wsdl:operation name="uploadFile">
|
||||||
|
<soap12:operation soapAction="urn:uploadFile" style="document"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<soap12:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
<wsdl:fault name="Exception">
|
||||||
|
<soap12:fault use="literal" name="Exception"/>
|
||||||
|
</wsdl:fault>
|
||||||
|
</wsdl:operation>
|
||||||
|
</wsdl:binding>
|
||||||
|
<wsdl:binding name="BeSimpleSwaServiceHttpBinding" type="ns:BeSimpleSwaServicePortType">
|
||||||
|
<http:binding verb="POST"/>
|
||||||
|
<wsdl:operation name="downloadFile">
|
||||||
|
<http:operation location="BeSimpleSwaService/downloadFile"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<mime:content type="text/xml" part="downloadFile"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<mime:content type="text/xml" part="downloadFile"/>
|
||||||
|
</wsdl:output>
|
||||||
|
</wsdl:operation>
|
||||||
|
<wsdl:operation name="uploadFile">
|
||||||
|
<http:operation location="BeSimpleSwaService/uploadFile"/>
|
||||||
|
<wsdl:input>
|
||||||
|
<mime:content type="text/xml" part="uploadFile"/>
|
||||||
|
</wsdl:input>
|
||||||
|
<wsdl:output>
|
||||||
|
<mime:content type="text/xml" part="uploadFile"/>
|
||||||
|
</wsdl:output>
|
||||||
|
</wsdl:operation>
|
||||||
|
</wsdl:binding>
|
||||||
|
<wsdl:service name="BeSimpleSwaService">
|
||||||
|
<wsdl:port name="BeSimpleSwaServiceHttpSoap11Endpoint" binding="ns:BeSimpleSwaServiceSoap11Binding">
|
||||||
|
<soap:address location="http://localhost:8080/axis2/services/BeSimpleSwaService.BeSimpleSwaServiceHttpSoap11Endpoint/"/>
|
||||||
|
</wsdl:port>
|
||||||
|
<wsdl:port name="BeSimpleSwaServiceHttpSoap12Endpoint" binding="ns:BeSimpleSwaServiceSoap12Binding">
|
||||||
|
<soap12:address location="http://localhost:8080/axis2/services/BeSimpleSwaService.BeSimpleSwaServiceHttpSoap12Endpoint/"/>
|
||||||
|
</wsdl:port>
|
||||||
|
<wsdl:port name="BeSimpleSwaServiceHttpEndpoint" binding="ns:BeSimpleSwaServiceHttpBinding">
|
||||||
|
<http:address location="http://localhost:8080/axis2/services/BeSimpleSwaService.BeSimpleSwaServiceHttpEndpoint/"/>
|
||||||
|
</wsdl:port>
|
||||||
|
</wsdl:service>
|
||||||
|
</wsdl:definitions>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<project name="BeSimpleSwaService" default="generate.service">
|
||||||
|
<property environment="env" />
|
||||||
|
<property name="axis2.home" value="C:/axis2" />
|
||||||
|
<property name="axis2.repo" value="${axis2.home}/repository" />
|
||||||
|
<property name="build.dir" value="build" />
|
||||||
|
<property name="filename" value="besimple-swa.aar" />
|
||||||
|
|
||||||
|
<path id="axis.classpath">
|
||||||
|
<fileset dir="${axis2.home}/lib">
|
||||||
|
<include name="*.jar" />
|
||||||
|
</fileset>
|
||||||
|
</path>
|
||||||
|
|
||||||
|
<target name="generate.service" depends="compile">
|
||||||
|
<jar destfile="${build.dir}/${filename}">
|
||||||
|
<fileset dir="resources/">
|
||||||
|
<include name="META-INF/services.xml" />
|
||||||
|
</fileset>
|
||||||
|
<fileset dir="${build.dir}/classes">
|
||||||
|
<include name="besimple/service/**/*.class" />
|
||||||
|
</fileset>
|
||||||
|
</jar>
|
||||||
|
<copy file="${build.dir}/${filename}" tofile="../axis_services/${filename}" overwrite="true" />
|
||||||
|
<copy file="${build.dir}/${filename}" tofile="${axis2.repo}/services/${filename}" overwrite="true" />
|
||||||
|
<antcall target="clean" />
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="compile">
|
||||||
|
<mkdir dir="${build.dir}/classes" />
|
||||||
|
<javac debug="on" srcdir="src" destdir="${build.dir}/classes">
|
||||||
|
<classpath refid="axis.classpath" />
|
||||||
|
</javac>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
<target name="clean">
|
||||||
|
<delete dir="${build.dir}" />
|
||||||
|
</target>
|
||||||
|
</project>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<serviceGroup>
|
||||||
|
<service name="BeSimpleSwaService">
|
||||||
|
<description>BeSimple test service for SwA.</description>
|
||||||
|
<parameter name="enableSwA">true</parameter>
|
||||||
|
<parameter name="ServiceClass" locked="false">besimple.service.BeSimpleSwaService</parameter>
|
||||||
|
<operation name="uploadFile">
|
||||||
|
<actionMapping>urn:uploadFile</actionMapping>
|
||||||
|
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
|
||||||
|
</operation>
|
||||||
|
<operation name="downloadFile">
|
||||||
|
<actionMapping>urn:downloadFile</actionMapping>
|
||||||
|
<messageReceiver class="org.apache.axis2.receivers.RawXMLINOutMessageReceiver"/>
|
||||||
|
</operation>
|
||||||
|
</service>
|
||||||
|
</serviceGroup>
|
|
@ -0,0 +1,78 @@
|
||||||
|
package besimple.service;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
|
import javax.activation.DataHandler;
|
||||||
|
import javax.activation.FileDataSource;
|
||||||
|
|
||||||
|
import org.apache.axiom.attachments.Attachments;
|
||||||
|
import org.apache.axiom.om.OMAbstractFactory;
|
||||||
|
import org.apache.axiom.om.OMAttribute;
|
||||||
|
import org.apache.axiom.om.OMElement;
|
||||||
|
import org.apache.axiom.om.OMFactory;
|
||||||
|
import org.apache.axiom.om.OMNamespace;
|
||||||
|
|
||||||
|
import org.apache.axis2.context.MessageContext;
|
||||||
|
import org.apache.axis2.context.OperationContext;
|
||||||
|
import org.apache.axis2.wsdl.WSDLConstants;
|
||||||
|
|
||||||
|
public class BeSimpleSwaService {
|
||||||
|
|
||||||
|
String namespace = "http://service.besimple";
|
||||||
|
|
||||||
|
public OMElement uploadFile(OMElement element) throws Exception {
|
||||||
|
OMElement dataElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "data"));
|
||||||
|
OMAttribute hrefAttribute = dataElement.getAttribute(new QName("href"));
|
||||||
|
|
||||||
|
String contentID = hrefAttribute.getAttributeValue();
|
||||||
|
contentID = contentID.trim();
|
||||||
|
if (contentID.substring(0, 3).equalsIgnoreCase("cid")) {
|
||||||
|
contentID = contentID.substring(4);
|
||||||
|
}
|
||||||
|
OMElement nameElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "name"));
|
||||||
|
String name = nameElement.getText();
|
||||||
|
|
||||||
|
MessageContext msgCtx = MessageContext.getCurrentMessageContext();
|
||||||
|
Attachments attachment = msgCtx.getAttachmentMap();
|
||||||
|
DataHandler dataHandler = attachment.getDataHandler(contentID);
|
||||||
|
|
||||||
|
File file = new File(name);
|
||||||
|
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||||
|
dataHandler.writeTo(fileOutputStream);
|
||||||
|
fileOutputStream.flush();
|
||||||
|
fileOutputStream.close();
|
||||||
|
|
||||||
|
OMFactory factory = OMAbstractFactory.getOMFactory();
|
||||||
|
OMNamespace omNs = factory.createOMNamespace(namespace, "swa");
|
||||||
|
OMElement wrapperElement = factory.createOMElement("uploadFileResponse", omNs);
|
||||||
|
OMElement returnElement = factory.createOMElement("return", omNs, wrapperElement);
|
||||||
|
returnElement.setText("File saved succesfully.");
|
||||||
|
|
||||||
|
return wrapperElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OMElement downloadFile(OMElement element) throws Exception {
|
||||||
|
OMElement nameElement = (OMElement)element.getFirstChildWithName(new QName(namespace, "name"));
|
||||||
|
String name = nameElement.getText();
|
||||||
|
|
||||||
|
MessageContext msgCtxIn = MessageContext.getCurrentMessageContext();
|
||||||
|
OperationContext operationContext = msgCtxIn.getOperationContext();
|
||||||
|
MessageContext msgCtxOut = operationContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
|
||||||
|
|
||||||
|
FileDataSource fileDataSource = new FileDataSource(name);
|
||||||
|
DataHandler dataHandler = new DataHandler(fileDataSource);
|
||||||
|
|
||||||
|
String contentID = "cid:" + msgCtxOut.addAttachment(dataHandler);
|
||||||
|
|
||||||
|
OMFactory factory = OMAbstractFactory.getOMFactory();
|
||||||
|
OMNamespace omNs = factory.createOMNamespace(namespace, "swa");
|
||||||
|
OMElement wrapperElement = factory.createOMElement("downloadFileResponse", omNs);
|
||||||
|
OMElement dataElement = factory.createOMElement("data", omNs, wrapperElement);
|
||||||
|
dataElement.addAttribute("href", contentID, null);
|
||||||
|
|
||||||
|
return wrapperElement;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient;
|
||||||
|
use BeSimple\SoapClient\WsAddressingFilter as BeSimpleWsAddressingFilter;
|
||||||
|
|
||||||
|
require '../bootstrap.php';
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'soap_version' => SOAP_1_2,
|
||||||
|
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
|
||||||
|
'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deploy "axis_services/version2.aar" to Apache Axis2 to get this example to
|
||||||
|
* work.
|
||||||
|
*
|
||||||
|
* To rebuild the "axis_services/version2.aar" the following steps need to be
|
||||||
|
* done to build a working Apache Axis2 version service with SOAP session
|
||||||
|
* enabled.
|
||||||
|
*
|
||||||
|
* 1) Go to $AXIS_HOME/samples/version and edit the following files:
|
||||||
|
*
|
||||||
|
* resources/META-INF/services.xml:
|
||||||
|
* <service name="Version2" scope="soapsession">
|
||||||
|
* ...
|
||||||
|
* </service>
|
||||||
|
*
|
||||||
|
* build.xml:
|
||||||
|
* replace version.aar with version2.aar
|
||||||
|
*
|
||||||
|
* 2) Run ant build.xml in "$AXIS_HOME/samples/version"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
$sc = new BeSimpleSoapClient('http://localhost:8080/axis2/services/Version2?wsdl', $options);
|
||||||
|
$soapKernel = $sc->getSoapKernel();
|
||||||
|
$wsaFilter = new BeSimpleWsAddressingFilter();
|
||||||
|
$soapKernel->registerFilter($wsaFilter);
|
||||||
|
|
||||||
|
//var_dump($sc->__getFunctions());
|
||||||
|
//var_dump($sc->__getTypes());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$wsaFilter->setReplyTo(BeSimpleWsAddressingFilter::ENDPOINT_REFERENCE_ANONYMOUS);
|
||||||
|
$wsaFilter->setMessageId();
|
||||||
|
|
||||||
|
var_dump($sc->getVersion());
|
||||||
|
|
||||||
|
$soapSessionId1 = $wsaFilter->getReferenceParameter('http://ws.apache.org/namespaces/axis2', 'ServiceGroupId');
|
||||||
|
echo 'ID1: ' .$soapSessionId1 . PHP_EOL;
|
||||||
|
|
||||||
|
$wsaFilter->addReferenceParameter('http://ws.apache.org/namespaces/axis2', 'axis2', 'ServiceGroupId', $soapSessionId1);
|
||||||
|
|
||||||
|
var_dump($sc->getVersion());
|
||||||
|
|
||||||
|
$soapSessionId2 = $wsaFilter->getReferenceParameter('http://ws.apache.org/namespaces/axis2', 'ServiceGroupId');
|
||||||
|
echo 'ID2: ' . $soapSessionId2 . PHP_EOL;
|
||||||
|
|
||||||
|
if ($soapSessionId1 == $soapSessionId2) {
|
||||||
|
echo PHP_EOL;
|
||||||
|
echo 'SOAP session worked :)';
|
||||||
|
}
|
||||||
|
} catch (Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// var_dump(
|
||||||
|
// $sc->__getLastRequestHeaders(),
|
||||||
|
// $sc->__getLastRequest(),
|
||||||
|
// $sc->__getLastResponseHeaders(),
|
||||||
|
// $sc->__getLastResponse()
|
||||||
|
// );
|
|
@ -0,0 +1,116 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use ass\XmlSecurity\Key as XmlSecurityKey;
|
||||||
|
|
||||||
|
use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient;
|
||||||
|
use BeSimple\SoapClient\WsSecurityFilter as BeSimpleWsSecurityFilter;
|
||||||
|
use BeSimple\SoapCommon\WsSecurityKey as BeSimpleWsSecurityKey;
|
||||||
|
|
||||||
|
require '../bootstrap.php';
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'soap_version' => SOAP_1_2,
|
||||||
|
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
|
||||||
|
'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deploy "axis_services/library-signencr.aar" to Apache Axis2 to get this
|
||||||
|
* example to work.
|
||||||
|
*
|
||||||
|
* Links:
|
||||||
|
* http://www.dcc.uchile.cl/~pcamacho/tutorial/web/xmlsec/xmlsec.html
|
||||||
|
* http://www.aleksey.com/xmlsec/xmldsig-verifier.html
|
||||||
|
*
|
||||||
|
* Using code from axis example:
|
||||||
|
* http://www.ibm.com/developerworks/java/library/j-jws5/index.html
|
||||||
|
*
|
||||||
|
* Download key tool to export private key
|
||||||
|
* http://couchpotato.net/pkeytool/
|
||||||
|
*
|
||||||
|
* keytool -export -alias serverkey -keystore server.keystore -storepass nosecret -file servercert.cer
|
||||||
|
* openssl x509 -out servercert.pem -outform pem -in servercert.pem -inform der
|
||||||
|
*
|
||||||
|
* keytool -export -alias clientkey -keystore client.keystore -storepass nosecret -file clientcert.cer
|
||||||
|
* openssl x509 -out clientcert.pem -outform pem -in clientcert.pem -inform der
|
||||||
|
* java -jar pkeytool.jar -exportkey -keystore client.keystore -storepass nosecret -keypass clientpass -rfc -alias clientkey -file clientkey.pem
|
||||||
|
*
|
||||||
|
* C:\Program Files\Java\jre6\bin\keytool -export -alias serverkey -keystore server.keystore -storepass nosecret -file servercert.cer
|
||||||
|
* C:\xampp\apache\bin\openssl x509 -out servercert.pem -outform pem -in servercert.cer -inform der
|
||||||
|
*
|
||||||
|
* C:\Program Files\Java\jre6\bin\keytool -export -alias clientkey -keystore client.keystore -storepass nosecret -file clientcert.cer
|
||||||
|
* C:\xampp\apache\bin\openssl x509 -out clientcert.pem -outform pem -in clientcert.cer -inform der
|
||||||
|
* java -jar C:\axis2\pkeytool\pkeytool.jar -exportkey -keystore client.keystore -storepass nosecret -keypass clientpass -rfc -alias clientkey -file clientkey.pem
|
||||||
|
*
|
||||||
|
* build.properties:
|
||||||
|
* server-policy=hash-policy-server.xml
|
||||||
|
*
|
||||||
|
* allows both text and digest!
|
||||||
|
*/
|
||||||
|
|
||||||
|
class getBook {}
|
||||||
|
class getBookResponse {}
|
||||||
|
class getBooksByType {}
|
||||||
|
class getBooksByTypeResponse {}
|
||||||
|
class addBook {}
|
||||||
|
class addBookResponse {}
|
||||||
|
class BookInformation {}
|
||||||
|
|
||||||
|
$options['classmap'] = array(
|
||||||
|
'getBook' => 'getBook',
|
||||||
|
'getBookResponse' => 'getBookResponse',
|
||||||
|
'getBooksByType' => 'getBooksByType',
|
||||||
|
'getBooksByTypeResponse' => 'getBooksByTypeResponse',
|
||||||
|
'addBook' => 'addBook',
|
||||||
|
'addBookResponse' => 'addBookResponse',
|
||||||
|
'BookInformation' => 'BookInformation',
|
||||||
|
);
|
||||||
|
|
||||||
|
$sc = new BeSimpleSoapClient('WsSecuritySigEnc.wsdl', $options);
|
||||||
|
|
||||||
|
$wssFilter = new BeSimpleWsSecurityFilter();
|
||||||
|
// user key for signature and encryption
|
||||||
|
$securityKeyUser = new BeSimpleWsSecurityKey();
|
||||||
|
$securityKeyUser->addPrivateKey(XmlSecurityKey::RSA_SHA1, 'clientkey.pem', true);
|
||||||
|
$securityKeyUser->addPublicKey(XmlSecurityKey::RSA_SHA1, 'clientcert.pem', true);
|
||||||
|
$wssFilter->setUserSecurityKeyObject($securityKeyUser);
|
||||||
|
// service key for encryption
|
||||||
|
$securityKeyService = new BeSimpleWsSecurityKey();
|
||||||
|
$securityKeyService->addPrivateKey(XmlSecurityKey::TRIPLEDES_CBC);
|
||||||
|
$securityKeyService->addPublicKey(XmlSecurityKey::RSA_1_5, 'servercert.pem', true);
|
||||||
|
$wssFilter->setServiceSecurityKeyObject($securityKeyService);
|
||||||
|
// TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | TOKEN_REFERENCE_SECURITY_TOKEN | TOKEN_REFERENCE_THUMBPRINT_SHA1
|
||||||
|
$wssFilter->setSecurityOptionsSignature(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_SECURITY_TOKEN);
|
||||||
|
$wssFilter->setSecurityOptionsEncryption(BeSimpleWsSecurityFilter::TOKEN_REFERENCE_THUMBPRINT_SHA1);
|
||||||
|
|
||||||
|
$soapKernel = $sc->getSoapKernel();
|
||||||
|
$soapKernel->registerFilter($wssFilter);
|
||||||
|
|
||||||
|
//var_dump($sc->__getFunctions());
|
||||||
|
//var_dump($sc->__getTypes());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$gb = new getBook();
|
||||||
|
$gb->isbn = '0061020052';
|
||||||
|
var_dump($sc->getBook($gb));
|
||||||
|
|
||||||
|
$ab = new addBook();
|
||||||
|
$ab->isbn = '0445203498';
|
||||||
|
$ab->title = 'The Dragon Never Sleeps';
|
||||||
|
$ab->author = 'Cook, Glen';
|
||||||
|
$ab->type = 'scifi';
|
||||||
|
var_dump($sc->addBook($ab));
|
||||||
|
|
||||||
|
// getBooksByType("scifi");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//var_dump(
|
||||||
|
// $sc->__getLastRequestHeaders(),
|
||||||
|
// $sc->__getLastRequest(),
|
||||||
|
// $sc->__getLastResponseHeaders(),
|
||||||
|
// $sc->__getLastResponse()
|
||||||
|
//);
|
|
@ -0,0 +1,184 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns:wns="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns:tns="http://ws.sosnoski.com/library/types"
|
||||||
|
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||||
|
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
|
||||||
|
<wsdl:types>
|
||||||
|
|
||||||
|
<schema elementFormDefault="qualified"
|
||||||
|
targetNamespace="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
||||||
|
|
||||||
|
<import namespace="http://ws.sosnoski.com/library/types"/>
|
||||||
|
|
||||||
|
<element name="getBook">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="isbn" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBookResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="getBookReturn" minOccurs="0" type="tns:BookInformation"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBooksByType">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="type" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBooksByTypeResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="getBooksByTypeReturn" minOccurs="0" maxOccurs="unbounded" type="tns:BookInformation"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="addBook">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="type" type="string"/>
|
||||||
|
<element name="isbn" type="string"/>
|
||||||
|
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
|
||||||
|
<element name="title" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="addBookResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="addBookReturn" type="boolean"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema elementFormDefault="qualified"
|
||||||
|
targetNamespace="http://ws.sosnoski.com/library/types"
|
||||||
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
||||||
|
|
||||||
|
<complexType name="BookInformation">
|
||||||
|
<sequence>
|
||||||
|
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
|
||||||
|
<element name="title" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
<attribute name="type" use="required" type="string"/>
|
||||||
|
<attribute name="isbn" use="required" type="string"/>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
</wsdl:types>
|
||||||
|
|
||||||
|
<wsdl:message name="getBookRequest">
|
||||||
|
<wsdl:part element="wns:getBook" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBookResponse">
|
||||||
|
<wsdl:part element="wns:getBookResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBooksByTypeRequest">
|
||||||
|
<wsdl:part element="wns:getBooksByType" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBooksByTypeResponse">
|
||||||
|
<wsdl:part element="wns:getBooksByTypeResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="addBookRequest">
|
||||||
|
<wsdl:part element="wns:addBook" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="addBookResponse">
|
||||||
|
<wsdl:part element="wns:addBookResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:portType name="Library">
|
||||||
|
|
||||||
|
<wsdl:operation name="getBook">
|
||||||
|
<wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
|
||||||
|
<wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBooksByType">
|
||||||
|
<wsdl:input message="wns:getBooksByTypeRequest" name="getBooksByTypeRequest"/>
|
||||||
|
<wsdl:output message="wns:getBooksByTypeResponse" name="getBooksByTypeResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="addBook">
|
||||||
|
<wsdl:input message="wns:addBookRequest" name="addBookRequest"/>
|
||||||
|
<wsdl:output message="wns:addBookResponse" name="addBookResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
</wsdl:portType>
|
||||||
|
|
||||||
|
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
|
||||||
|
|
||||||
|
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBook">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:getBook"/>
|
||||||
|
|
||||||
|
<wsdl:input name="getBookRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="getBookResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBooksByType">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:getBooksByType"/>
|
||||||
|
|
||||||
|
<wsdl:input name="getBooksByTypeRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="getBooksByTypeResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="addBook">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:addBook"/>
|
||||||
|
|
||||||
|
<wsdl:input name="addBookRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="addBookResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
</wsdl:binding>
|
||||||
|
|
||||||
|
<wsdl:service name="library-signencr">
|
||||||
|
|
||||||
|
<wsdl:port binding="wns:LibrarySoapBinding" name="library">
|
||||||
|
<wsdlsoap:address location="http://localhost:8080/axis2/services/library-signencr"/>
|
||||||
|
</wsdl:port>
|
||||||
|
|
||||||
|
</wsdl:service>
|
||||||
|
|
||||||
|
</wsdl:definitions>
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use BeSimple\SoapClient\SoapClient as BeSimpleSoapClient;
|
||||||
|
use BeSimple\SoapClient\WsSecurityFilter as BeSimpleWsSecurityFilter;
|
||||||
|
|
||||||
|
require '../bootstrap.php';
|
||||||
|
|
||||||
|
echo '<pre>';
|
||||||
|
|
||||||
|
$options = array(
|
||||||
|
'soap_version' => SOAP_1_2,
|
||||||
|
'features' => SOAP_SINGLE_ELEMENT_ARRAYS, // make sure that result is array for size=1
|
||||||
|
'trace' => true, // enables use of the methods SoapClient->__getLastRequest, SoapClient->__getLastRequestHeaders, SoapClient->__getLastResponse and SoapClient->__getLastResponseHeaders
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deploy "axis_services/library-username-digest.aar" to Apache Axis2 to get
|
||||||
|
* this example to work.
|
||||||
|
*
|
||||||
|
* Using code from axis example:
|
||||||
|
* http://www.ibm.com/developerworks/java/library/j-jws4/index.html
|
||||||
|
*
|
||||||
|
* build.properties:
|
||||||
|
* server-policy=hash-policy-server.xml
|
||||||
|
*
|
||||||
|
* allows both text and digest!
|
||||||
|
*/
|
||||||
|
|
||||||
|
class getBook {}
|
||||||
|
class getBookResponse {}
|
||||||
|
class getBooksByType {}
|
||||||
|
class getBooksByTypeResponse {}
|
||||||
|
class addBook {}
|
||||||
|
class addBookResponse {}
|
||||||
|
class BookInformation {}
|
||||||
|
|
||||||
|
$options['classmap'] = array(
|
||||||
|
'getBook' => 'getBook',
|
||||||
|
'getBookResponse' => 'getBookResponse',
|
||||||
|
'getBooksByType' => 'getBooksByType',
|
||||||
|
'getBooksByTypeResponse' => 'getBooksByTypeResponse',
|
||||||
|
'addBook' => 'addBook',
|
||||||
|
'addBookResponse' => 'addBookResponse',
|
||||||
|
'BookInformation' => 'BookInformation',
|
||||||
|
);
|
||||||
|
|
||||||
|
$sc = new BeSimpleSoapClient('WsSecurityUserPass.wsdl', $options);
|
||||||
|
|
||||||
|
$wssFilter = new BeSimpleWsSecurityFilter(true, 600);
|
||||||
|
$wssFilter->addUserData('libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_TEXT);
|
||||||
|
//$wssFilter->addUserData( 'libuser', 'books', BeSimpleWsSecurityFilter::PASSWORD_TYPE_DIGEST );
|
||||||
|
|
||||||
|
$soapKernel = $sc->getSoapKernel();
|
||||||
|
$soapKernel->registerFilter($wssFilter);
|
||||||
|
|
||||||
|
//var_dump($sc->__getFunctions());
|
||||||
|
//var_dump($sc->__getTypes());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$gb = new getBook();
|
||||||
|
$gb->isbn = '0061020052';
|
||||||
|
var_dump($sc->getBook($gb));
|
||||||
|
|
||||||
|
$ab = new addBook();
|
||||||
|
$ab->isbn = '0445203498';
|
||||||
|
$ab->title = 'The Dragon Never Sleeps';
|
||||||
|
$ab->author = 'Cook, Glen';
|
||||||
|
$ab->type = 'scifi';
|
||||||
|
var_dump($sc->addBook($ab));
|
||||||
|
|
||||||
|
// getBooksByType("scifi");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
var_dump($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
//var_dump(
|
||||||
|
// $sc->__getLastRequestHeaders(),
|
||||||
|
// $sc->__getLastRequest(),
|
||||||
|
// $sc->__getLastResponseHeaders(),
|
||||||
|
// $sc->__getLastResponse()
|
||||||
|
//);
|
|
@ -0,0 +1,184 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns:wns="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns:tns="http://ws.sosnoski.com/library/types"
|
||||||
|
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||||
|
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">
|
||||||
|
<wsdl:types>
|
||||||
|
|
||||||
|
<schema elementFormDefault="qualified"
|
||||||
|
targetNamespace="http://ws.sosnoski.com/library/wsdl"
|
||||||
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
||||||
|
|
||||||
|
<import namespace="http://ws.sosnoski.com/library/types"/>
|
||||||
|
|
||||||
|
<element name="getBook">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="isbn" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBookResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="getBookReturn" minOccurs="0" type="tns:BookInformation"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBooksByType">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="type" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="getBooksByTypeResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="getBooksByTypeReturn" minOccurs="0" maxOccurs="unbounded" type="tns:BookInformation"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="addBook">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="type" type="string"/>
|
||||||
|
<element name="isbn" type="string"/>
|
||||||
|
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
|
||||||
|
<element name="title" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
<element name="addBookResponse">
|
||||||
|
<complexType>
|
||||||
|
<sequence>
|
||||||
|
<element name="addBookReturn" type="boolean"/>
|
||||||
|
</sequence>
|
||||||
|
</complexType>
|
||||||
|
</element>
|
||||||
|
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
<schema elementFormDefault="qualified"
|
||||||
|
targetNamespace="http://ws.sosnoski.com/library/types"
|
||||||
|
xmlns="http://www.w3.org/2001/XMLSchema">
|
||||||
|
|
||||||
|
<complexType name="BookInformation">
|
||||||
|
<sequence>
|
||||||
|
<element name="author" minOccurs="0" maxOccurs="unbounded" type="string"/>
|
||||||
|
<element name="title" type="string"/>
|
||||||
|
</sequence>
|
||||||
|
<attribute name="type" use="required" type="string"/>
|
||||||
|
<attribute name="isbn" use="required" type="string"/>
|
||||||
|
</complexType>
|
||||||
|
|
||||||
|
</schema>
|
||||||
|
|
||||||
|
</wsdl:types>
|
||||||
|
|
||||||
|
<wsdl:message name="getBookRequest">
|
||||||
|
<wsdl:part element="wns:getBook" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBookResponse">
|
||||||
|
<wsdl:part element="wns:getBookResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBooksByTypeRequest">
|
||||||
|
<wsdl:part element="wns:getBooksByType" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="getBooksByTypeResponse">
|
||||||
|
<wsdl:part element="wns:getBooksByTypeResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="addBookRequest">
|
||||||
|
<wsdl:part element="wns:addBook" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:message name="addBookResponse">
|
||||||
|
<wsdl:part element="wns:addBookResponse" name="parameters"/>
|
||||||
|
</wsdl:message>
|
||||||
|
|
||||||
|
<wsdl:portType name="Library">
|
||||||
|
|
||||||
|
<wsdl:operation name="getBook">
|
||||||
|
<wsdl:input message="wns:getBookRequest" name="getBookRequest"/>
|
||||||
|
<wsdl:output message="wns:getBookResponse" name="getBookResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBooksByType">
|
||||||
|
<wsdl:input message="wns:getBooksByTypeRequest" name="getBooksByTypeRequest"/>
|
||||||
|
<wsdl:output message="wns:getBooksByTypeResponse" name="getBooksByTypeResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="addBook">
|
||||||
|
<wsdl:input message="wns:addBookRequest" name="addBookRequest"/>
|
||||||
|
<wsdl:output message="wns:addBookResponse" name="addBookResponse"/>
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
</wsdl:portType>
|
||||||
|
|
||||||
|
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
|
||||||
|
|
||||||
|
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBook">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:getBook"/>
|
||||||
|
|
||||||
|
<wsdl:input name="getBookRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="getBookResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="getBooksByType">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:getBooksByType"/>
|
||||||
|
|
||||||
|
<wsdl:input name="getBooksByTypeRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="getBooksByTypeResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
<wsdl:operation name="addBook">
|
||||||
|
|
||||||
|
<wsdlsoap:operation soapAction="urn:addBook"/>
|
||||||
|
|
||||||
|
<wsdl:input name="addBookRequest">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:input>
|
||||||
|
|
||||||
|
<wsdl:output name="addBookResponse">
|
||||||
|
<wsdlsoap:body use="literal"/>
|
||||||
|
</wsdl:output>
|
||||||
|
|
||||||
|
</wsdl:operation>
|
||||||
|
|
||||||
|
</wsdl:binding>
|
||||||
|
|
||||||
|
<wsdl:service name="library-username">
|
||||||
|
|
||||||
|
<wsdl:port binding="wns:LibrarySoapBinding" name="library">
|
||||||
|
<wsdlsoap:address location="http://localhost:8080/axis2/services/library-username"/>
|
||||||
|
</wsdl:port>
|
||||||
|
|
||||||
|
</wsdl:service>
|
||||||
|
|
||||||
|
</wsdl:definitions>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,17 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICoDCCAgkCBEnhw2IwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAk5aMRMw
|
||||||
|
EQYDVQQIEwpXZWxsaW5ndG9uMRowGAYDVQQHExFQYXJhcGFyYXVtdSBCZWFjaDEq
|
||||||
|
MCgGA1UEChMhU29zbm9za2kgU29mdHdhcmUgQXNzb2NpYXRlcyBMdGQuMRAwDgYD
|
||||||
|
VQQLEwdVbmtub3duMRgwFgYDVQQDEw9EZW5uaXMgU29zbm9za2kwHhcNMDkwNDEy
|
||||||
|
MTAzMzA2WhcNMzYwODI3MTAzMzA2WjCBljELMAkGA1UEBhMCTloxEzARBgNVBAgT
|
||||||
|
CldlbGxpbmd0b24xGjAYBgNVBAcTEVBhcmFwYXJhdW11IEJlYWNoMSowKAYDVQQK
|
||||||
|
EyFTb3Nub3NraSBTb2Z0d2FyZSBBc3NvY2lhdGVzIEx0ZC4xEDAOBgNVBAsTB1Vu
|
||||||
|
a25vd24xGDAWBgNVBAMTD0Rlbm5pcyBTb3Nub3NraTCBnzANBgkqhkiG9w0BAQEF
|
||||||
|
AAOBjQAwgYkCgYEAhOVyNK8xyxtb4DnKtU6mF9KoiFqCk7eKoLE26+9h410CtTkx
|
||||||
|
zWAfgnR+8i+LPbdsPY+yXAo6NYpCCKolXfDLe+AG2GwnMZGrIl6+BLF3hqTmIXBF
|
||||||
|
TLGUmC7A7uBTivaWgdH1w3hb33rASoVU67BVtQ3QQi99juZX4vU9o9pScocCAwEA
|
||||||
|
ATANBgkqhkiG9w0BAQUFAAOBgQBMNPo1KAGbz8Jl6HGbtAcetieSJ3bEAXmv1tcj
|
||||||
|
ysBS67AXzdu1Ac+onHh2EpzBM7kuGbw+trU+AhulooPpewIQRApXP1F0KHRDcbqW
|
||||||
|
jwvknS6HnomN9572giLGKn2601bHiRUj35hiA8aLmMUBppIRPFFAoQ0QUBCPx+m8
|
||||||
|
/0n33w==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,14 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAITlcjSvMcsbW+A5yrVOphfSqIha
|
||||||
|
gpO3iqCxNuvvYeNdArU5Mc1gH4J0fvIviz23bD2PslwKOjWKQgiqJV3wy3vgBthsJzGRqyJevgSx
|
||||||
|
d4ak5iFwRUyxlJguwO7gU4r2loHR9cN4W996wEqFVOuwVbUN0EIvfY7mV+L1PaPaUnKHAgMBAAEC
|
||||||
|
gYAZ6UqtLwN8YGc3fs0hMKZ9upsViuAuwPiMgED/G3twgzAF+ZLWQkmie+hMfCyf6eV200+pVm0n
|
||||||
|
Bz/8xH/oowxpX0Kk3szoB4vFghjU84GKUcrbhu/NRIm7l3drnfbzqhQkHDCx6n1CotI4Gs49cDWu
|
||||||
|
4uEAuxJkEIVY553unZjZgQJBAOJVIallNKmD0iQlvtWRmRzpmYDjt9vhNY6WBTIOx6SDn9SRaoSA
|
||||||
|
fkipQ2HXo04r78TQ674+zfZ1lRTkFG7px6ECQQCWUPHp3pSZOM1oGzJrNvNaw+MizZAZjq34npHm
|
||||||
|
9GRquFLG7BlCaI9QNGE7pN2ryYsYCRUMaM2e4GR0tUXxVGknAkAgrxqFU9AfCqI2Bh1gyf3KZxF7
|
||||||
|
w2axofwR8ygc6nV6FGfoUneHWubhp0/LuVAj4cRmL6Vbe8ZSaPh2Y9lviuMBAkEAicP8Q+1E4j1m
|
||||||
|
PPEYP51oYprANOiUFmhnWEL00+jPk+QFsd03tV6hYs/vAbwzkjuwqMHCMdJoCiH8z95IEUvc5wJA
|
||||||
|
MvLOuZdu4dmhOXg/YKsbMSPjFNEVskLQNSXqw6O2wIrpPg1NQvBBAOTbiuZj3vind4VPos1wc4vB
|
||||||
|
QocvdUC6dA==
|
||||||
|
-----END PRIVATE KEY-----
|
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
|
@ -0,0 +1,17 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICoDCCAgkCBEnhwzMwDQYJKoZIhvcNAQEFBQAwgZYxCzAJBgNVBAYTAk5aMRMw
|
||||||
|
EQYDVQQIEwpXZWxsaW5ndG9uMRowGAYDVQQHExFQYXJhcGFyYXVtdSBCZWFjaDEq
|
||||||
|
MCgGA1UEChMhU29zbm9za2kgU29mdHdhcmUgQXNzb2NpYXRlcyBMdGQuMRAwDgYD
|
||||||
|
VQQLEwdVbmtub3duMRgwFgYDVQQDEw9EZW5uaXMgU29zbm9za2kwHhcNMDkwNDEy
|
||||||
|
MTAzMjE5WhcNMzYwODI3MTAzMjE5WjCBljELMAkGA1UEBhMCTloxEzARBgNVBAgT
|
||||||
|
CldlbGxpbmd0b24xGjAYBgNVBAcTEVBhcmFwYXJhdW11IEJlYWNoMSowKAYDVQQK
|
||||||
|
EyFTb3Nub3NraSBTb2Z0d2FyZSBBc3NvY2lhdGVzIEx0ZC4xEDAOBgNVBAsTB1Vu
|
||||||
|
a25vd24xGDAWBgNVBAMTD0Rlbm5pcyBTb3Nub3NraTCBnzANBgkqhkiG9w0BAQEF
|
||||||
|
AAOBjQAwgYkCgYEA1H3mjQCF9uce2jmm/Yq9kE4ytfvkp4c8G90cDfJXJvOiGQds
|
||||||
|
p2vDZXKuCkHQ7vsBBXPNTt8J/d8ZbEwyuB9Ccz5pJqi6Ig6Y2/mEsPthDyh5SrJV
|
||||||
|
yQ/wxUGwmfSuwdrIMnplMTq+OR9BOfT3CvjSvuy9d6BQNo4wOMkDvmZTtI8CAwEA
|
||||||
|
ATANBgkqhkiG9w0BAQUFAAOBgQCqv4475QaqlKcN2QCZJbLVKZEX+76XLQurGkgf
|
||||||
|
2fCgesRHjfUfOHyTTlhWQdEKTcBB2XviUyyW6I//fmKfXUIiQqvgh4LHdXRPEXDf
|
||||||
|
Y9nr89MjyQpDlnl6AlrvSej30a9iwVRUeVk4d6gxWHMRonKBFgh+TGexxUXHtPkf
|
||||||
|
B1Pdtg==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -0,0 +1,180 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapClient\Curl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class CurlTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $webserverProcessId;
|
||||||
|
|
||||||
|
protected function startPhpWebserver()
|
||||||
|
{
|
||||||
|
if ('Windows' == substr(php_uname('s'), 0, 7 )) {
|
||||||
|
$powershellCommand = "\$app = start-process php.exe -ArgumentList '-S localhost:8000 -t ".__DIR__.DIRECTORY_SEPARATOR."Fixtures' -WindowStyle 'Hidden' -passthru; Echo \$app.Id;";
|
||||||
|
$shellCommand = 'powershell -command "& {'.$powershellCommand.'}"';
|
||||||
|
} else {
|
||||||
|
$shellCommand = "nohup php -S localhost:8000 -t ".__DIR__.DIRECTORY_SEPARATOR."Fixtures &";
|
||||||
|
}
|
||||||
|
$output = array();
|
||||||
|
exec($shellCommand, $output);
|
||||||
|
$this->webserverProcessId = $output[0]; // pid is in first element
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function stopPhpWebserver()
|
||||||
|
{
|
||||||
|
if (!is_null($this->webserverProcessId)) {
|
||||||
|
if ('Windows' == substr(php_uname('s'), 0, 7 )) {
|
||||||
|
exec('TASKKILL /F /PID ' . $this->webserverProcessId);
|
||||||
|
} else {
|
||||||
|
exec('kill ' . $this->webserverProcessId);
|
||||||
|
}
|
||||||
|
$this->webserverProcessId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExec()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$this->assertTrue($curl->exec('http://localhost:8000/curl.txt'));
|
||||||
|
$this->assertTrue($curl->exec('http://localhost:8000/404.txt'));
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetErrorMessage()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://unknown/curl.txt');
|
||||||
|
$this->assertEquals('Could not connect to host', $curl->getErrorMessage());
|
||||||
|
|
||||||
|
$curl->exec('xyz://localhost:8000/@404.txt');
|
||||||
|
$this->assertEquals('Unknown protocol. Only http and https are allowed.', $curl->getErrorMessage());
|
||||||
|
|
||||||
|
$curl->exec('');
|
||||||
|
$this->assertEquals('Unable to parse URL', $curl->getErrorMessage());
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetRequestHeaders()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals(136, strlen($curl->getRequestHeaders()));
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals(135, strlen($curl->getRequestHeaders()));
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponse()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals(150, strlen($curl->getResponse()));
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals(1282, strlen($curl->getResponse()));
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponseBody()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals('This is a testfile for cURL.', $curl->getResponseBody());
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponseContentType()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals('text/plain; charset=UTF-8', $curl->getResponseContentType());
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals('text/html; charset=UTF-8', $curl->getResponseContentType());
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponseHeaders()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals(122, strlen($curl->getResponseHeaders()));
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals(130, strlen($curl->getResponseHeaders()));
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponseStatusCode()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals(200, $curl->getResponseStatusCode());
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals(404, $curl->getResponseStatusCode());
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetResponseStatusMessage()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/curl.txt');
|
||||||
|
$this->assertEquals('OK', $curl->getResponseStatusMessage());
|
||||||
|
|
||||||
|
$curl->exec('http://localhost:8000/404.txt');
|
||||||
|
$this->assertEquals('Not Found', $curl->getResponseStatusMessage());
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
This is a testfile for cURL.
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
|
||||||
|
<xs:element name="note">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="to" type="xs:string"/>
|
||||||
|
<xs:element name="from" type="xs:string"/>
|
||||||
|
<xs:element name="heading" type="xs:string"/>
|
||||||
|
<xs:element name="body" type="xs:string"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
|
||||||
|
</xs:schema>
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<wsdl:types xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://test.sample">
|
||||||
|
<xs:element name="note">
|
||||||
|
<xs:complexType>
|
||||||
|
<xs:sequence>
|
||||||
|
<xs:element name="to" type="xs:string"/>
|
||||||
|
<xs:element name="from" type="xs:string"/>
|
||||||
|
<xs:element name="heading" type="xs:string"/>
|
||||||
|
<xs:element name="body" type="xs:string"/>
|
||||||
|
</xs:sequence>
|
||||||
|
</xs:complexType>
|
||||||
|
</xs:element>
|
||||||
|
</xs:schema>
|
||||||
|
</wsdl:types>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<wsdl:documentation>wsdlincludetest</wsdl:documentation>
|
||||||
|
<wsdl:include location="http://localhost:8000/wsdl_include.wsdl"/>
|
||||||
|
</wsdl:definitions>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<wsdl:documentation>wsdlincludetest</wsdl:documentation>
|
||||||
|
<wsdl:include location="../wsdl_include.wsdl"/>
|
||||||
|
</wsdl:definitions>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<wsdl:documentation>xsdinctest</wsdl:documentation>
|
||||||
|
<wsdl:types>
|
||||||
|
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://test.sample">
|
||||||
|
<xs:include schemaLocation="http://localhost:8000/type_include.xsd"/>
|
||||||
|
</xs:schema>
|
||||||
|
</wsdl:types>
|
||||||
|
</wsdl:definitions>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<wsdl:documentation>xsdinctest</wsdl:documentation>
|
||||||
|
<wsdl:types>
|
||||||
|
<xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://test.sample">
|
||||||
|
<xs:include schemaLocation="../type_include.xsd"/>
|
||||||
|
</xs:schema>
|
||||||
|
</wsdl:types>
|
||||||
|
</wsdl:definitions>
|
|
@ -1,113 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the BeSimpleSoapBundle.
|
|
||||||
*
|
|
||||||
* (c) Christian Kerl <christian-kerl@web.de>
|
|
||||||
* (c) Francis Besset <francis.besset@gmail.com>
|
|
||||||
*
|
|
||||||
* This source file is subject to the MIT license that is bundled
|
|
||||||
* with this source code in the file LICENSE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace BeSimple\Tests\SoapClient;
|
|
||||||
|
|
||||||
use BeSimple\SoapClient\SoapRequest;
|
|
||||||
|
|
||||||
class SoapRequestTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testSetFunction()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
$soapRequest->setFunction('foo');
|
|
||||||
|
|
||||||
$this->assertEquals('foo', $soapRequest->getFunction());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetArguments()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
$arguments = array(
|
|
||||||
'foo' => true,
|
|
||||||
'bar' => false,
|
|
||||||
);
|
|
||||||
$soapRequest->setArguments($arguments);
|
|
||||||
|
|
||||||
$this->assertEquals($arguments, $soapRequest->getArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetArgument()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
|
|
||||||
$this->assertSame(null, $soapRequest->getArgument('foo'));
|
|
||||||
$this->assertFalse($soapRequest->getArgument('foo', false));
|
|
||||||
|
|
||||||
$soapRequest->addArgument('foo', 'bar');
|
|
||||||
|
|
||||||
$this->assertEquals('bar', $soapRequest->getArgument('foo', false));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetOptions()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
$options = array(
|
|
||||||
'uri' => 'foo',
|
|
||||||
'soapaction' => 'bar',
|
|
||||||
);
|
|
||||||
$soapRequest->setOptions($options);
|
|
||||||
|
|
||||||
$this->assertEquals($options, $soapRequest->getOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testGetOption()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
|
|
||||||
$this->assertSame(null, $soapRequest->getOption('soapaction'));
|
|
||||||
$this->assertFalse($soapRequest->getOption('soapaction', false));
|
|
||||||
|
|
||||||
$soapRequest->addOption('soapaction', 'foo');
|
|
||||||
|
|
||||||
$this->assertEquals('foo', $soapRequest->getOption('soapaction'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testSetHeaders()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
|
|
||||||
$this->assertEquals(null, $soapRequest->getHeaders());
|
|
||||||
|
|
||||||
$header1 = new \SoapHeader('foobar', 'foo', 'bar');
|
|
||||||
$header2 = new \SoapHeader('barfoo', 'bar', 'foo');
|
|
||||||
$soapRequest
|
|
||||||
->addHeader($header1)
|
|
||||||
->addHeader($header2)
|
|
||||||
;
|
|
||||||
|
|
||||||
$this->assertSame(array($header1, $header2), $soapRequest->getHeaders());
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testConstruct()
|
|
||||||
{
|
|
||||||
$soapRequest = new SoapRequest();
|
|
||||||
|
|
||||||
$this->assertNull($soapRequest->getFunction());
|
|
||||||
$this->assertEquals(array(), $soapRequest->getArguments());
|
|
||||||
$this->assertEquals(array(), $soapRequest->getOptions());
|
|
||||||
$this->assertEquals(null, $soapRequest->getHeaders());
|
|
||||||
|
|
||||||
$arguments = array('bar' => 'foobar');
|
|
||||||
$options = array('soapaction' => 'foobar');
|
|
||||||
$headers = array(
|
|
||||||
new \SoapHeader('foobar', 'foo', 'bar'),
|
|
||||||
new \SoapHeader('barfoo', 'bar', 'foo'),
|
|
||||||
);
|
|
||||||
$soapRequest = new SoapRequest('foo', $arguments, $options, $headers);
|
|
||||||
|
|
||||||
$this->assertEquals('foo', $soapRequest->getFunction());
|
|
||||||
$this->assertEquals($arguments, $soapRequest->getArguments());
|
|
||||||
$this->assertEquals($options, $soapRequest->getOptions());
|
|
||||||
$this->assertSame($headers, $soapRequest->getHeaders());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,265 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the BeSimpleSoapClient.
|
||||||
|
*
|
||||||
|
* (c) Christian Kerl <christian-kerl@web.de>
|
||||||
|
* (c) Francis Besset <francis.besset@gmail.com>
|
||||||
|
*
|
||||||
|
* This source file is subject to the MIT license that is bundled
|
||||||
|
* with this source code in the file LICENSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace BeSimple\SoapClient;
|
||||||
|
|
||||||
|
use BeSimple\SoapClient\WsdlDownloader;
|
||||||
|
use BeSimple\SoapClient\Curl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andreas Schamberger <mail@andreass.net>
|
||||||
|
*/
|
||||||
|
class WsdlDownloaderTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $webserverProcessId;
|
||||||
|
|
||||||
|
protected function startPhpWebserver()
|
||||||
|
{
|
||||||
|
if ('Windows' == substr(php_uname('s'), 0, 7 )) {
|
||||||
|
$powershellCommand = "\$app = start-process php.exe -ArgumentList '-S localhost:8000 -t ".__DIR__.DIRECTORY_SEPARATOR."Fixtures' -WindowStyle 'Hidden' -passthru; Echo \$app.Id;";
|
||||||
|
$shellCommand = 'powershell -command "& {'.$powershellCommand.'}"';
|
||||||
|
} else {
|
||||||
|
$shellCommand = "nohup php -S localhost:8000 -t ".__DIR__.DIRECTORY_SEPARATOR."Fixtures &";
|
||||||
|
}
|
||||||
|
$output = array();
|
||||||
|
exec($shellCommand, $output);
|
||||||
|
$this->webserverProcessId = $output[0]; // pid is in first element
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function stopPhpWebserver()
|
||||||
|
{
|
||||||
|
if (!is_null($this->webserverProcessId)) {
|
||||||
|
if ('Windows' == substr(php_uname('s'), 0, 7 )) {
|
||||||
|
exec('TASKKILL /F /PID ' . $this->webserverProcessId);
|
||||||
|
} else {
|
||||||
|
exec('kill ' . $this->webserverProcessId);
|
||||||
|
}
|
||||||
|
$this->webserverProcessId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDownload()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
$wd = new WsdlDownloader($curl);
|
||||||
|
|
||||||
|
$cacheDir = ini_get('soap.wsdl_cache_dir');
|
||||||
|
if (!is_dir($cacheDir)) {
|
||||||
|
$cacheDir = sys_get_temp_dir();
|
||||||
|
$cacheDirForRegExp = preg_quote( $cacheDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
$tests = array(
|
||||||
|
'localWithAbsolutePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_absolute.xml',
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'localWithRelativePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_relative.xml',
|
||||||
|
'assertRegExp' => '~.*\.\./type_include\.xsd.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => 'http://localhost:8000/xsdinclude/xsdinctest_absolute.xml',
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => 'http://localhost:8000/xsdinclude/xsdinctest_relative.xml',
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($tests as $name => $values) {
|
||||||
|
$cacheFileName = $wd->download($values['source']);
|
||||||
|
$result = file_get_contents($cacheFileName);
|
||||||
|
$this->assertRegExp($values['assertRegExp'],$result,$name);
|
||||||
|
unlink($cacheFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIsRemoteFile()
|
||||||
|
{
|
||||||
|
$curl = new Curl();
|
||||||
|
$wd = new WsdlDownloader($curl);
|
||||||
|
|
||||||
|
$class = new \ReflectionClass($wd);
|
||||||
|
$method = $class->getMethod('isRemoteFile');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://www.php.net/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://localhost/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://mylocaldomain/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://www.php.net/dir/test.html'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://localhost/dir/test.html'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'http://mylocaldomain/dir/test.html'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://www.php.net/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://localhost/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://mylocaldomain/'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://www.php.net/dir/test.html'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://localhost/dir/test.html'));
|
||||||
|
$this->assertTrue($method->invoke($wd, 'https://mylocaldomain/dir/test.html'));
|
||||||
|
$this->assertFalse($method->invoke($wd, 'c:/dir/test.html'));
|
||||||
|
$this->assertFalse($method->invoke($wd, '/dir/test.html'));
|
||||||
|
$this->assertFalse($method->invoke($wd, '../dir/test.html'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveWsdlIncludes()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
$wd = new WsdlDownloader($curl);
|
||||||
|
|
||||||
|
$class = new \ReflectionClass($wd);
|
||||||
|
$method = $class->getMethod('resolveRemoteIncludes');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
|
||||||
|
$cacheDir = ini_get('soap.wsdl_cache_dir');
|
||||||
|
if (!is_dir($cacheDir)) {
|
||||||
|
$cacheDir = sys_get_temp_dir();
|
||||||
|
$cacheDirForRegExp = preg_quote( $cacheDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
$remoteUrlAbsolute = 'http://localhost:8000/wsdlinclude/wsdlinctest_absolute.xml';
|
||||||
|
$remoteUrlRelative = 'http://localhost:8000/wsdlinclude/wsdlinctest_relative.xml';
|
||||||
|
$tests = array(
|
||||||
|
'localWithAbsolutePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/wsdlinclude/wsdlinctest_absolute.xml',
|
||||||
|
'cacheFile' => $cacheDir.'/cache_local_absolute.xml',
|
||||||
|
'remoteParentUrl' => null,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'localWithRelativePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/wsdlinclude/wsdlinctest_relative.xml',
|
||||||
|
'cacheFile' => $cacheDir.'/cache_local_relative.xml',
|
||||||
|
'remoteParentUrl' => null,
|
||||||
|
'assertRegExp' => '~.*\.\./wsdl_include\.wsdl.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => $remoteUrlAbsolute,
|
||||||
|
'cacheFile' => $cacheDir.'/cache_remote_absolute.xml',
|
||||||
|
'remoteParentUrl' => $remoteUrlAbsolute,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => $remoteUrlRelative,
|
||||||
|
'cacheFile' => $cacheDir.'/cache_remote_relative.xml',
|
||||||
|
'remoteParentUrl' => $remoteUrlRelative,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($tests as $name => $values) {
|
||||||
|
$wsdl = file_get_contents( $values['source'] );
|
||||||
|
$method->invoke($wd, $wsdl, $values['cacheFile'],$values['remoteParentUrl']);
|
||||||
|
$result = file_get_contents($values['cacheFile']);
|
||||||
|
$this->assertRegExp($values['assertRegExp'],$result,$name);
|
||||||
|
unlink($values['cacheFile']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveXsdIncludes()
|
||||||
|
{
|
||||||
|
$this->startPhpWebserver();
|
||||||
|
|
||||||
|
$curl = new Curl();
|
||||||
|
$wd = new WsdlDownloader($curl);
|
||||||
|
|
||||||
|
$class = new \ReflectionClass($wd);
|
||||||
|
$method = $class->getMethod('resolveRemoteIncludes');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
|
||||||
|
$cacheDir = ini_get('soap.wsdl_cache_dir');
|
||||||
|
if (!is_dir($cacheDir)) {
|
||||||
|
$cacheDir = sys_get_temp_dir();
|
||||||
|
$cacheDirForRegExp = preg_quote( $cacheDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
$remoteUrlAbsolute = 'http://localhost:8000/xsdinclude/xsdinctest_absolute.xml';
|
||||||
|
$remoteUrlRelative = 'http://localhost:8000/xsdinclude/xsdinctest_relative.xml';
|
||||||
|
$tests = array(
|
||||||
|
'localWithAbsolutePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_absolute.xml',
|
||||||
|
'cacheFile' => $cacheDir.'/cache_local_absolute.xml',
|
||||||
|
'remoteParentUrl' => null,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'localWithRelativePath' => array(
|
||||||
|
'source' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/xsdinclude/xsdinctest_relative.xml',
|
||||||
|
'cacheFile' => $cacheDir.'/cache_local_relative.xml',
|
||||||
|
'remoteParentUrl' => null,
|
||||||
|
'assertRegExp' => '~.*\.\./type_include\.xsd.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => $remoteUrlAbsolute,
|
||||||
|
'cacheFile' => $cacheDir.'/cache_remote_absolute.xml',
|
||||||
|
'remoteParentUrl' => $remoteUrlAbsolute,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
'remoteWithAbsolutePath' => array(
|
||||||
|
'source' => $remoteUrlRelative,
|
||||||
|
'cacheFile' => $cacheDir.'/cache_remote_relative.xml',
|
||||||
|
'remoteParentUrl' => $remoteUrlRelative,
|
||||||
|
'assertRegExp' => '~.*'.$cacheDirForRegExp.'\\\wsdl_.*\.cache.*~',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($tests as $name => $values) {
|
||||||
|
$wsdl = file_get_contents( $values['source'] );
|
||||||
|
$method->invoke($wd, $wsdl, $values['cacheFile'],$values['remoteParentUrl']);
|
||||||
|
$result = file_get_contents($values['cacheFile']);
|
||||||
|
$this->assertRegExp($values['assertRegExp'],$result,$name);
|
||||||
|
unlink($values['cacheFile']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stopPhpWebserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testResolveRelativePathInUrl()
|
||||||
|
{
|
||||||
|
$curl = new Curl();
|
||||||
|
$wd = new WsdlDownloader($curl);
|
||||||
|
|
||||||
|
$class = new \ReflectionClass($wd);
|
||||||
|
$method = $class->getMethod('resolveRelativePathInUrl');
|
||||||
|
$method->setAccessible(true);
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost:8080/test', $method->invoke($wd, 'http://localhost:8080/sub', '/test'));
|
||||||
|
$this->assertEquals('http://localhost:8080/test', $method->invoke($wd, 'http://localhost:8080/sub/', '/test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub', '/test'));
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/', '/test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost', './test'));
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/', './test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/sub/test', $method->invoke($wd, 'http://localhost/sub/sub', './test'));
|
||||||
|
$this->assertEquals('http://localhost/sub/sub/test', $method->invoke($wd, 'http://localhost/sub/sub/', './test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/sub', '../test'));
|
||||||
|
$this->assertEquals('http://localhost/sub/test', $method->invoke($wd, 'http://localhost/sub/sub/', '../test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/sub/sub', '../../test'));
|
||||||
|
$this->assertEquals('http://localhost/sub/test', $method->invoke($wd, 'http://localhost/sub/sub/sub/', '../../test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/sub/sub/sub', '../../../test'));
|
||||||
|
$this->assertEquals('http://localhost/sub/test', $method->invoke($wd, 'http://localhost/sub/sub/sub/sub/', '../../../test'));
|
||||||
|
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/sub/sub', '../../../test'));
|
||||||
|
$this->assertEquals('http://localhost/test', $method->invoke($wd, 'http://localhost/sub/sub/sub/', '../../../test'));
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,13 @@ spl_autoload_register(function($class) {
|
||||||
if (file_exists($path) && is_readable($path)) {
|
if (file_exists($path) && is_readable($path)) {
|
||||||
require_once $path;
|
require_once $path;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} elseif (0 === strpos($class, 'ass\XmlSecurity\\')) {
|
||||||
|
$path = __DIR__.'/../vendor/XmlSecurity/src/'.strtr($class, '\\', '/').'.php';
|
||||||
|
if (file_exists($path) && is_readable($path)) {
|
||||||
|
require_once $path;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} elseif (0 === strpos($class, 'BeSimple\SoapCommon\\')) {
|
} elseif (0 === strpos($class, 'BeSimple\SoapCommon\\')) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ if (!is_dir($vendorDir = dirname(__FILE__).'/vendor')) {
|
||||||
|
|
||||||
$deps = array(
|
$deps = array(
|
||||||
array('besimple-soapcommon', 'http://github.com/BeSimple/BeSimpleSoapCommon.git', 'origin/HEAD'),
|
array('besimple-soapcommon', 'http://github.com/BeSimple/BeSimpleSoapCommon.git', 'origin/HEAD'),
|
||||||
|
array('XmlSecurity', 'https://github.com/aschamberger/XmlSecurity.git', 'origin/HEAD'),
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($deps as $dep) {
|
foreach ($deps as $dep) {
|
||||||
|
|
Loading…
Reference in New Issue