From 247f9ae5dacc8bd778d6aa113591cff86dafc53d Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 1 Nov 2011 10:45:02 +0100 Subject: [PATCH 1/5] added WsdlHandler --- src/BeSimple/SoapCommon/WsdlHandler.php | 206 ++++++++++++++++++ .../SoapCommon/Fixtures/WsdlMimeContent.wsdl | 64 ++++++ .../SoapCommon/Fixtures/WsdlMimeContent2.wsdl | 64 ++++++ .../SoapCommon/Fixtures/WsdlMimeContent3.wsdl | 64 ++++++ .../Tests/SoapCommon/WsdlHandlerTest.php | 48 ++++ 5 files changed, 446 insertions(+) create mode 100644 src/BeSimple/SoapCommon/WsdlHandler.php create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent.wsdl create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent2.wsdl create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent3.wsdl create mode 100644 tests/BeSimple/Tests/SoapCommon/WsdlHandlerTest.php diff --git a/src/BeSimple/SoapCommon/WsdlHandler.php b/src/BeSimple/SoapCommon/WsdlHandler.php new file mode 100644 index 0000000..cec21f5 --- /dev/null +++ b/src/BeSimple/SoapCommon/WsdlHandler.php @@ -0,0 +1,206 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon; + +/** + * This class loads the given WSDL file and allows to check MIME binding + * information. + * + * @author Andreas Schamberger + */ +class WsdlHandler +{ + /** + * Binding type 'input' . + */ + const BINDING_OPERATION_INPUT = 'input'; + + /** + * Binding type 'output' . + */ + const BINDING_OPERATION_OUTPUT = 'output'; + + /** + * WSDL 1.1 namespace. + */ + const NS_WSDL = 'http://schemas.xmlsoap.org/wsdl/'; + + /** + * WSDL MIME namespace. + */ + const NS_WSDL_MIME = 'http://schemas.xmlsoap.org/wsdl/mime/'; + + /** + * WSDL SOAP 1.1 namespace. + */ + const NS_WSDL_SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'; + + /** + * WSDL SOAP 1.2 namespace. + */ + const NS_WSDL_SOAP_1_2 = 'http://schemas.xmlsoap.org/wsdl/soap12/'; + + /** + * WSDL file name. + * + * @var string + */ + private $wsdlFile; + + /** + * DOMDocument WSDL file. + * + * @var \DOMDocument + */ + private $domDocument; + + /** + * DOMXPath WSDL file. + * + * @var DOMXPath + */ + private $domXpath; + + /** + * Array of mime type information. + * + * @var array(string=>array(string=>array(string=>array(string)))) + */ + private $mimeTypes = array(); + + /** + * WSDL namespace of current WSDL file. + * + * @var string + */ + private $wsdlSoapNamespace; + + /** + * Constructor. + * + * @param string $wsdlFile WSDL file name + * @param string $soapVersion SOAP version constant + */ + public function __construct($wsdlFile, $soapVersion) + { + $this->wsdlFile = $wsdlFile; + if ($soapVersion == SOAP_1_1) { + $this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_1; + } else { + $this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_2; + } + $this->domDocument = new \DOMDocument('1.0', 'utf-8'); + $this->domDocument->load($this->wsdlFile); + $this->domXpath = new \DOMXPath($this->domDocument); + $this->domXpath->registerNamespace('wsdl', self::NS_WSDL); + $this->domXpath->registerNamespace('mime', self::NS_WSDL_MIME); + $this->domXpath->registerNamespace('soap', $this->wsdlSoapNamespace); + } + + /** + * Gets the mime type information from the WSDL file. + * + * @param string $soapAction Soap action to analyse + * @return array(string=>array(string=>array(string))) + */ + private function getMimeTypesForSoapAction($soapAction) + { + $query = '/wsdl:definitions/wsdl:binding/wsdl:operation/soap:operation[@soapAction="'.$soapAction.'"]/..'; + $nodes = $this->domXpath->query($query); + $mimeTypes = array(); + if (($wsdlOperation = $nodes->item(0)) !== null) { + //$wsdlOperationName = $wsdlOperation->getAttribute('name'); + foreach ($wsdlOperation->childNodes as $soapOperationChild) { + // wsdl:input or wsdl:output + if ($soapOperationChild->localName == 'input' || $soapOperationChild->localName == 'output') { + $operationType = $soapOperationChild->localName; + // mime:multipartRelated/mime:part + $mimeParts = $soapOperationChild->getElementsByTagNameNS(self::NS_WSDL_MIME, 'part'); + if ($mimeParts->length > 0) { + foreach ($mimeParts as $mimePart) { + foreach ($mimePart->childNodes as $child) { + switch ($child->localName) { + case 'body': + $parts = $child->getAttribute('parts'); + $parts = ($parts == '') ? '[body]' : $parts; + $mimeTypes[$operationType][$parts] = array('text/xml'); + break; + case 'content': + $part = $child->getAttribute('part'); + $part = ($part == '') ? null : $part; + $type = $child->getAttribute('type'); + $type = ($type == '') ? '*/*' : $type; + if (!isset($mimeTypes[$operationType][$part])) { + $mimeTypes[$operationType][$part] = array(); + } + $mimeTypes[$operationType][$part][] = $type; + break; + case 'mimeXml': + // this does not conform to the spec + $part = $child->getAttribute('part'); + $part = ($part == '') ? null : $part; + $mimeTypes[$operationType][$part] = array('text/xml'); + break; + } + } + } + } else { + $child = $soapOperationChild->getElementsByTagNameNS($this->wsdlSoapNamespace, 'body')->item(0); + if (!is_null($child)) { + $parts = $child->getAttribute('parts'); + $parts = ($parts == '') ? '[body]' : $parts; + $mimeTypes[$operationType][$parts] = array('text/xml'); + } + } + } + } + } + return $mimeTypes; + } + + /** + * Checks the mime type of the part for the given operation. + * + * @param string $soapAction Soap action + * @param string $operationType Operation type + * @param string $part Part name + * @param string $currentMimeType Current mime type + * @return boolean + */ + public function isValidMimeTypeType($soapAction, $operationType, $part, $currentMimeType) + { + // load data from WSDL + if (!isset($this->mimeTypes[$soapAction])) { + $this->mimeTypes[$soapAction] = $this->getMimeTypesForSoapAction($soapAction); + } + // part is valid as we do not have an explicit entry for current part + if (!isset($this->mimeTypes[$soapAction][$operationType][$part])) { + return true; + } + $mimeTypes = $this->mimeTypes[$soapAction][$operationType][$part]; + // wildcard or exact match + if (in_array('*/*', $mimeTypes) || in_array($currentMimeType, $mimeTypes)) { + return true; + // type/* match + } else { + list($ctype, $csubtype) = explode('/', $currentMimeType); + foreach ($mimeTypes as $mimeType) { + list($type, $subtype) = explode('/', $mimeType); + if ($subtype == '*' && $type == $ctype) { + return true; + } + } + } + return false; + } +} \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent.wsdl b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent.wsdl new file mode 100644 index 0000000..30984b3 --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent.wsdl @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent2.wsdl b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent2.wsdl new file mode 100644 index 0000000..a6168da --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent2.wsdl @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent3.wsdl b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent3.wsdl new file mode 100644 index 0000000..c7e1d82 --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/WsdlMimeContent3.wsdl @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapCommon/WsdlHandlerTest.php b/tests/BeSimple/Tests/SoapCommon/WsdlHandlerTest.php new file mode 100644 index 0000000..7c10c92 --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/WsdlHandlerTest.php @@ -0,0 +1,48 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\Tests\SoapCommon\Soap; + +use BeSimple\SoapCommon\WsdlHandler; + +class WsdlHandlerTest extends \PHPUnit_Framework_TestCase +{ + public function testIsValidMimeTypeType() + { + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent.wsdl'; + $wh = new WsdlHandler($filename, SOAP_1_1); + + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml')); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent2.wsdl'; + $wh = new WsdlHandler($filename, SOAP_1_1); + + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml')); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/WsdlMimeContent3.wsdl'; + $wh = new WsdlHandler($filename, SOAP_1_1); + + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'text/xml')); + $this->assertFalse($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'body', 'image/gif')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/jpeg')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'image/gif')); + $this->assertTrue($wh->isValidMimeTypeType('http://example.com/soapaction', WsdlHandler::BINDING_OPERATION_INPUT, 'ClaimPhoto', 'text/xml')); + } +} \ No newline at end of file From 4ea60adcb7b41304597ba2763680d07560af279d Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 1 Nov 2011 11:12:07 +0100 Subject: [PATCH 2/5] added WsSecurityKey --- src/BeSimple/SoapCommon/WsSecurityKey.php | 114 +++++++++++++++++ .../Tests/SoapCommon/Fixtures/clientcert.pem | 17 +++ .../Tests/SoapCommon/Fixtures/clientkey.pem | 14 +++ .../Tests/SoapCommon/Fixtures/servercert.pem | 17 +++ .../Tests/SoapCommon/WsSecurityKeyTest.php | 119 ++++++++++++++++++ tests/bootstrap.php | 9 +- vendors.php | 1 + 7 files changed, 290 insertions(+), 1 deletion(-) create mode 100644 src/BeSimple/SoapCommon/WsSecurityKey.php create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/clientcert.pem create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/clientkey.pem create mode 100644 tests/BeSimple/Tests/SoapCommon/Fixtures/servercert.pem create mode 100644 tests/BeSimple/Tests/SoapCommon/WsSecurityKeyTest.php mode change 100755 => 100644 vendors.php diff --git a/src/BeSimple/SoapCommon/WsSecurityKey.php b/src/BeSimple/SoapCommon/WsSecurityKey.php new file mode 100644 index 0000000..6eaf908 --- /dev/null +++ b/src/BeSimple/SoapCommon/WsSecurityKey.php @@ -0,0 +1,114 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\SoapCommon; + +use ass\XmlSecurity\Key as XmlSecurityKey; + +/** + * This class represents a security key for WS-Security (WSS). + * + * @author Andreas Schamberger + */ +class WsSecurityKey +{ + /** + * Private key. + * + * @var \ass\XmlSecurity\Key + */ + protected $privateKey = null; + + /** + * Public key. + * + * @var \ass\XmlSecurity\Key + */ + protected $publicKey = null; + + /** + * Add private key. + * + * @param string $encryptionType Encryption type + * @param string $key Private key + * @param boolean $keyIsFile Given key parameter is path to key file + * @param string $passphrase Passphrase for key + * @return void + */ + public function addPrivateKey($encryptionType, $key = null, $keyIsFile = true, $passphrase = null) + { + $this->privateKey = XmlSecurityKey::factory($encryptionType, $key, $keyIsFile, XmlSecurityKey::TYPE_PRIVATE, $passphrase); + } + + /** + * Add public key. + * + * @param string $encryptionType Encryption type + * @param string $key Public key + * @param boolean $keyIsFile Given key parameter is path to key file + * @return void + */ + public function addPublicKey($encryptionType, $key = null, $keyIsFile = true) + { + $this->publicKey = XmlSecurityKey::factory($encryptionType, $key, $keyIsFile, XmlSecurityKey::TYPE_PUBLIC); + } + + /** + * Get private key. + * + * @return \ass\XmlSecurity\Key + */ + public function getPrivateKey() + { + return $this->privateKey; + } + + /** + * Get public key. + * + * @return \ass\XmlSecurity\Key + */ + public function getPublicKey() + { + return $this->publicKey; + } + + /** + * Has private and public key? + * + * @return boolean + */ + public function hasKeys() + { + return !is_null($this->privateKey) && !is_null($this->publicKey); + } + + /** + * Has private key? + * + * @return boolean + */ + public function hasPrivateKey() + { + return !is_null($this->privateKey); + } + + /** + * Has public key? + * + * @return boolean + */ + public function hasPublicKey() + { + return !is_null($this->publicKey); + } +} \ No newline at end of file diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/clientcert.pem b/tests/BeSimple/Tests/SoapCommon/Fixtures/clientcert.pem new file mode 100644 index 0000000..f433d48 --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/clientcert.pem @@ -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----- diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/clientkey.pem b/tests/BeSimple/Tests/SoapCommon/Fixtures/clientkey.pem new file mode 100644 index 0000000..a47f923 --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/clientkey.pem @@ -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----- diff --git a/tests/BeSimple/Tests/SoapCommon/Fixtures/servercert.pem b/tests/BeSimple/Tests/SoapCommon/Fixtures/servercert.pem new file mode 100644 index 0000000..040b22c --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/Fixtures/servercert.pem @@ -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----- diff --git a/tests/BeSimple/Tests/SoapCommon/WsSecurityKeyTest.php b/tests/BeSimple/Tests/SoapCommon/WsSecurityKeyTest.php new file mode 100644 index 0000000..3571d3c --- /dev/null +++ b/tests/BeSimple/Tests/SoapCommon/WsSecurityKeyTest.php @@ -0,0 +1,119 @@ + + * (c) Francis Besset + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace BeSimple\Tests\SoapCommon\Soap; + +use BeSimple\SoapCommon\WsSecurityKey; +use ass\XmlSecurity\Key as XmlSecurityKey; + +class WsSecurityKeyTest extends \PHPUnit_Framework_TestCase +{ + public function testHasKeys() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientkey.pem'; + $wsk->addPrivateKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientcert.pem'; + $wsk->addPublicKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + + $this->assertTrue($wsk->hasKeys()); + $this->assertTrue($wsk->hasPrivateKey()); + $this->assertTrue($wsk->hasPublicKey()); + } + + public function testHasKeysNone() + { + $wsk = new WsSecurityKey(); + + $this->assertFalse($wsk->hasKeys()); + $this->assertFalse($wsk->hasPrivateKey()); + $this->assertFalse($wsk->hasPublicKey()); + } + + public function testHasPrivateKey() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientkey.pem'; + $wsk->addPrivateKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + + $this->assertFalse($wsk->hasKeys()); + $this->assertTrue($wsk->hasPrivateKey()); + } + + public function testHasPublicKey() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientcert.pem'; + $wsk->addPublicKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + + $this->assertFalse($wsk->hasKeys()); + $this->assertTrue($wsk->hasPublicKey()); + } + + public function testAddPrivateKey() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientkey.pem'; + $wsk->addPrivateKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + + $this->assertTrue($wsk->hasPrivateKey()); + $this->assertInstanceOf('ass\XmlSecurity\Key', $wsk->getPrivateKey()); + } + + public function testAddPrivateKeySessionKey() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientkey.pem'; + $wsk->addPrivateKey(\ass\XmlSecurity\Key::TRIPLEDES_CBC); + + $this->assertTrue($wsk->hasPrivateKey()); + $this->assertInstanceOf('ass\XmlSecurity\Key', $wsk->getPrivateKey()); + } + + public function testAddPrivateKeyNoFile() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientkey.pem'; + $wsk->addPrivateKey(\ass\XmlSecurity\Key::RSA_SHA1, file_get_contents($filename), false); + + $this->assertTrue($wsk->hasPrivateKey()); + $this->assertInstanceOf('ass\XmlSecurity\Key', $wsk->getPrivateKey()); + } + + public function testAddPublicKey() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientcert.pem'; + $wsk->addPublicKey(\ass\XmlSecurity\Key::RSA_SHA1, $filename); + + $this->assertTrue($wsk->hasPublicKey()); + $this->assertInstanceOf('ass\XmlSecurity\Key', $wsk->getPublicKey()); + } + + public function testAddPublicKeyNoFile() + { + $wsk = new WsSecurityKey(); + + $filename = __DIR__.DIRECTORY_SEPARATOR.'Fixtures/clientcert.pem'; + $wsk->addPublicKey(\ass\XmlSecurity\Key::RSA_SHA1, file_get_contents($filename), false); + + $this->assertTrue($wsk->hasPublicKey()); + $this->assertInstanceOf('ass\XmlSecurity\Key', $wsk->getPublicKey()); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 69c30f0..f2d913c 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,7 +12,14 @@ spl_autoload_register(function($class) { return true; } } elseif (0 === strpos($class, 'BeSimple\SoapCommon\\')) { - $path = __DIR__.'/../src/'.($class = strtr($class, '\\', '/')).'.php'; + $path = __DIR__.'/../src/'.strtr($class, '\\', '/').'.php'; + if (file_exists($path) && is_readable($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; diff --git a/vendors.php b/vendors.php old mode 100755 new mode 100644 index 7f127b0..6180e27 --- a/vendors.php +++ b/vendors.php @@ -25,6 +25,7 @@ if (!is_dir($vendorDir = dirname(__FILE__).'/vendor')) { $deps = array( array('vfsStream', 'https://github.com/mikey179/vfsStream.git', 'RELEASE-0.10.1'), + array('XmlSecurity', 'https://github.com/aschamberger/XmlSecurity.git', 'origin/HEAD'), ); foreach ($deps as $dep) { From 3d906dc97a7e3e4002f5123f6bc875901afec7d3 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Tue, 1 Nov 2011 17:17:16 +0100 Subject: [PATCH 3/5] load WSDL file into DOM only if necessary --- src/BeSimple/SoapCommon/WsdlHandler.php | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/BeSimple/SoapCommon/WsdlHandler.php b/src/BeSimple/SoapCommon/WsdlHandler.php index cec21f5..28ab5b5 100644 --- a/src/BeSimple/SoapCommon/WsdlHandler.php +++ b/src/BeSimple/SoapCommon/WsdlHandler.php @@ -99,12 +99,6 @@ class WsdlHandler } else { $this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_2; } - $this->domDocument = new \DOMDocument('1.0', 'utf-8'); - $this->domDocument->load($this->wsdlFile); - $this->domXpath = new \DOMXPath($this->domDocument); - $this->domXpath->registerNamespace('wsdl', self::NS_WSDL); - $this->domXpath->registerNamespace('mime', self::NS_WSDL_MIME); - $this->domXpath->registerNamespace('soap', $this->wsdlSoapNamespace); } /** @@ -179,6 +173,8 @@ class WsdlHandler */ public function isValidMimeTypeType($soapAction, $operationType, $part, $currentMimeType) { + // create DOMDocument from WSDL file + $this->loadWsdlInDom(); // load data from WSDL if (!isset($this->mimeTypes[$soapAction])) { $this->mimeTypes[$soapAction] = $this->getMimeTypesForSoapAction($soapAction); @@ -203,4 +199,21 @@ class WsdlHandler } return false; } + + /** + * Loads the WSDL file into a DOM + * + * @return void + */ + private function loadWsdlInDom() + { + if (is_null($this->domDocument)) { + $this->domDocument = new \DOMDocument('1.0', 'utf-8'); + $this->domDocument->load($this->wsdlFile); + $this->domXpath = new \DOMXPath($this->domDocument); + $this->domXpath->registerNamespace('wsdl', self::NS_WSDL); + $this->domXpath->registerNamespace('mime', self::NS_WSDL_MIME); + $this->domXpath->registerNamespace('soap', $this->wsdlSoapNamespace); + } + } } \ No newline at end of file From c7e8928dfae8190090444363c7c542ae62d0b311 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sun, 4 Dec 2011 15:38:23 +0100 Subject: [PATCH 4/5] move wsdl namespace constants to Helper --- src/BeSimple/SoapCommon/Helper.php | 25 +++++++++++++++++++ src/BeSimple/SoapCommon/WsdlHandler.php | 32 ++++++------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/BeSimple/SoapCommon/Helper.php b/src/BeSimple/SoapCommon/Helper.php index 58f9779..19185ed 100644 --- a/src/BeSimple/SoapCommon/Helper.php +++ b/src/BeSimple/SoapCommon/Helper.php @@ -71,6 +71,26 @@ class Helper */ const NS_WSA = 'http://www.w3.org/2005/08/addressing'; + /** + * WSDL 1.1 namespace. + */ + const NS_WSDL = 'http://schemas.xmlsoap.org/wsdl/'; + + /** + * WSDL MIME namespace. + */ + const NS_WSDL_MIME = 'http://schemas.xmlsoap.org/wsdl/mime/'; + + /** + * WSDL SOAP 1.1 namespace. + */ + const NS_WSDL_SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'; + + /** + * WSDL SOAP 1.2 namespace. + */ + const NS_WSDL_SOAP_1_2 = 'http://schemas.xmlsoap.org/wsdl/soap12/'; + /** * Web Services Security Extension namespace. */ @@ -106,6 +126,11 @@ class Helper */ const PFX_WSA = 'wsa'; + /** + * WSDL 1.1 namespace. prefix. + */ + const PFX_WSDL = 'wsdl'; + /** * Web Services Security Extension namespace. */ diff --git a/src/BeSimple/SoapCommon/WsdlHandler.php b/src/BeSimple/SoapCommon/WsdlHandler.php index 28ab5b5..d358ba6 100644 --- a/src/BeSimple/SoapCommon/WsdlHandler.php +++ b/src/BeSimple/SoapCommon/WsdlHandler.php @@ -12,6 +12,8 @@ namespace BeSimple\SoapCommon; +use BeSimple\SoapCommon\Helper; + /** * This class loads the given WSDL file and allows to check MIME binding * information. @@ -30,26 +32,6 @@ class WsdlHandler */ const BINDING_OPERATION_OUTPUT = 'output'; - /** - * WSDL 1.1 namespace. - */ - const NS_WSDL = 'http://schemas.xmlsoap.org/wsdl/'; - - /** - * WSDL MIME namespace. - */ - const NS_WSDL_MIME = 'http://schemas.xmlsoap.org/wsdl/mime/'; - - /** - * WSDL SOAP 1.1 namespace. - */ - const NS_WSDL_SOAP_1_1 = 'http://schemas.xmlsoap.org/wsdl/soap/'; - - /** - * WSDL SOAP 1.2 namespace. - */ - const NS_WSDL_SOAP_1_2 = 'http://schemas.xmlsoap.org/wsdl/soap12/'; - /** * WSDL file name. * @@ -95,9 +77,9 @@ class WsdlHandler { $this->wsdlFile = $wsdlFile; if ($soapVersion == SOAP_1_1) { - $this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_1; + $this->wsdlSoapNamespace = Helper::NS_WSDL_SOAP_1_1; } else { - $this->wsdlSoapNamespace = self::NS_WSDL_SOAP_1_2; + $this->wsdlSoapNamespace = Helper::NS_WSDL_SOAP_1_2; } } @@ -119,7 +101,7 @@ class WsdlHandler if ($soapOperationChild->localName == 'input' || $soapOperationChild->localName == 'output') { $operationType = $soapOperationChild->localName; // mime:multipartRelated/mime:part - $mimeParts = $soapOperationChild->getElementsByTagNameNS(self::NS_WSDL_MIME, 'part'); + $mimeParts = $soapOperationChild->getElementsByTagNameNS(Helper::NS_WSDL_MIME, 'part'); if ($mimeParts->length > 0) { foreach ($mimeParts as $mimePart) { foreach ($mimePart->childNodes as $child) { @@ -211,8 +193,8 @@ class WsdlHandler $this->domDocument = new \DOMDocument('1.0', 'utf-8'); $this->domDocument->load($this->wsdlFile); $this->domXpath = new \DOMXPath($this->domDocument); - $this->domXpath->registerNamespace('wsdl', self::NS_WSDL); - $this->domXpath->registerNamespace('mime', self::NS_WSDL_MIME); + $this->domXpath->registerNamespace('wsdl', Helper::NS_WSDL); + $this->domXpath->registerNamespace('mime', Helper::NS_WSDL_MIME); $this->domXpath->registerNamespace('soap', $this->wsdlSoapNamespace); } } From a39af089f4cfabbe7dbfcc40029cb8ba5dae2240 Mon Sep 17 00:00:00 2001 From: Andreas Schamberger Date: Sun, 4 Dec 2011 17:29:50 +0100 Subject: [PATCH 5/5] cs fixes --- src/BeSimple/SoapCommon/WsSecurityKey.php | 6 +++--- src/BeSimple/SoapCommon/WsdlHandler.php | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/BeSimple/SoapCommon/WsSecurityKey.php b/src/BeSimple/SoapCommon/WsSecurityKey.php index 6eaf908..327b521 100644 --- a/src/BeSimple/SoapCommon/WsSecurityKey.php +++ b/src/BeSimple/SoapCommon/WsSecurityKey.php @@ -89,7 +89,7 @@ class WsSecurityKey */ public function hasKeys() { - return !is_null($this->privateKey) && !is_null($this->publicKey); + return null !== $this->privateKey && null !== $this->publicKey; } /** @@ -99,7 +99,7 @@ class WsSecurityKey */ public function hasPrivateKey() { - return !is_null($this->privateKey); + return null !== $this->privateKey; } /** @@ -109,6 +109,6 @@ class WsSecurityKey */ public function hasPublicKey() { - return !is_null($this->publicKey); + return null !== $this->publicKey; } } \ No newline at end of file diff --git a/src/BeSimple/SoapCommon/WsdlHandler.php b/src/BeSimple/SoapCommon/WsdlHandler.php index d358ba6..f0f533e 100644 --- a/src/BeSimple/SoapCommon/WsdlHandler.php +++ b/src/BeSimple/SoapCommon/WsdlHandler.php @@ -94,7 +94,7 @@ class WsdlHandler $query = '/wsdl:definitions/wsdl:binding/wsdl:operation/soap:operation[@soapAction="'.$soapAction.'"]/..'; $nodes = $this->domXpath->query($query); $mimeTypes = array(); - if (($wsdlOperation = $nodes->item(0)) !== null) { + if (null !== $wsdlOperation = $nodes->item(0)) { //$wsdlOperationName = $wsdlOperation->getAttribute('name'); foreach ($wsdlOperation->childNodes as $soapOperationChild) { // wsdl:input or wsdl:output @@ -132,7 +132,7 @@ class WsdlHandler } } else { $child = $soapOperationChild->getElementsByTagNameNS($this->wsdlSoapNamespace, 'body')->item(0); - if (!is_null($child)) { + if (null !== $child) { $parts = $child->getAttribute('parts'); $parts = ($parts == '') ? '[body]' : $parts; $mimeTypes[$operationType][$parts] = array('text/xml'); @@ -141,6 +141,7 @@ class WsdlHandler } } } + return $mimeTypes; } @@ -179,6 +180,7 @@ class WsdlHandler } } } + return false; } @@ -189,7 +191,7 @@ class WsdlHandler */ private function loadWsdlInDom() { - if (is_null($this->domDocument)) { + if (null === $this->domDocument) { $this->domDocument = new \DOMDocument('1.0', 'utf-8'); $this->domDocument->load($this->wsdlFile); $this->domXpath = new \DOMXPath($this->domDocument);