From 5edca6fb787057cc12ea8b5e58743338dc84fdeb Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 21 Oct 2020 12:09:52 +0200 Subject: [PATCH 01/10] Allow PHP 8.0 and dump PHPUnit dep Signed-off-by: Filippo Tessarotto --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 0b1ccaa..a23eb6e 100644 --- a/composer.json +++ b/composer.json @@ -25,12 +25,12 @@ } }, "require": { - "php": "^5.6 || ^7.0", + "php": "^7.3 || ~8.0.0", "laminas/laminas-zendframework-bridge": "^1.0" }, "require-dev": { "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^5.7.23 || ^6.4.3" + "phpunit/phpunit": "^9.4.2" }, "autoload": { "psr-4": { From 8e36b14ff8a580110b7098a5fa185d5878f804d0 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 21 Oct 2020 12:10:03 +0200 Subject: [PATCH 02/10] Make tests pass Signed-off-by: Filippo Tessarotto --- src/Document.php | 2 -- test/DOMXPathTest.php | 2 +- test/Document/NodeListTest.php | 2 +- test/Document/QueryTest.php | 18 +++++++++--------- test/DocumentTest.php | 26 +++++++++++--------------- 5 files changed, 22 insertions(+), 28 deletions(-) diff --git a/src/Document.php b/src/Document.php index e403095..aa78e56 100644 --- a/src/Document.php +++ b/src/Document.php @@ -231,7 +231,6 @@ protected function setErrors($errors) protected function getDomDocumentFromString($stringDocument) { libxml_use_internal_errors(true); - libxml_disable_entity_loader(true); $encoding = $this->getEncoding(); $domDoc = null === $encoding ? new DOMDocument('1.0') : new DOMDocument('1.0', $encoding); @@ -261,7 +260,6 @@ protected function getDomDocumentFromString($stringDocument) libxml_clear_errors(); } - libxml_disable_entity_loader(false); libxml_use_internal_errors(false); if (! $success) { diff --git a/test/DOMXPathTest.php b/test/DOMXPathTest.php index 11674e4..ead689d 100644 --- a/test/DOMXPathTest.php +++ b/test/DOMXPathTest.php @@ -19,7 +19,7 @@ class DOMXPathTest extends TestCase /** @var DOMDocument */ private $document; - protected function setUp() + protected function setUp(): void { $this->document = new DOMDocument(''); } diff --git a/test/Document/NodeListTest.php b/test/Document/NodeListTest.php index 143d317..56386db 100644 --- a/test/Document/NodeListTest.php +++ b/test/Document/NodeListTest.php @@ -26,7 +26,7 @@ class NodeListTest extends TestCase /** @var NodeList|DOMNode[] */ private $nodeList; - protected function setUp() + protected function setUp(): void { $document = new DOMDocument(); $document->loadHTML(''); diff --git a/test/Document/QueryTest.php b/test/Document/QueryTest.php index d134ad7..1ec576e 100644 --- a/test/Document/QueryTest.php +++ b/test/Document/QueryTest.php @@ -19,7 +19,7 @@ class QueryTest extends TestCase public function testTransformShouldReturnStringByDefault() { $test = Query::cssToXpath(''); - $this->assertInternalType('string', $test); + $this->assertIsString($test); } /** @@ -28,8 +28,8 @@ public function testTransformShouldReturnStringByDefault() public function testTransformShouldReturnMultiplePathsWhenExpressionContainsCommas() { $test = Query::cssToXpath('#foo, #bar'); - $this->assertInternalType('string', $test); - $this->assertContains('|', $test); + $this->assertIsString($test); + $this->assertStringContainsString('|', $test); $this->assertCount(2, explode('|', $test)); } @@ -48,13 +48,13 @@ public function testTransformShouldRecognizeDotSymbolAsClass() public function testTransformShouldAssumeSpacesToIndicateRelativeXpathQueries() { $test = Query::cssToXpath('div#foo .bar'); - $this->assertContains('|', $test); + $this->assertStringContainsString('|', $test); $expected = [ "//div[@id='foo']//*[contains(concat(' ', normalize-space(@class), ' '), ' bar ')]", "//div[@id='foo'][contains(concat(' ', normalize-space(@class), ' '), ' bar ')]", ]; foreach ($expected as $path) { - $this->assertContains($path, $test); + $this->assertStringContainsString($path, $test); } } @@ -70,8 +70,8 @@ public function testTransformShouldWriteChildSelectorsAsAbsoluteXpathRelations() public function testMultipleComplexCssSpecificationShouldTransformToExpectedXpath() { $test = Query::cssToXpath('div#foo span.bar, #bar li.baz a'); - $this->assertInternalType('string', $test); - $this->assertContains('|', $test); + $this->assertIsString($test); + $this->assertStringContainsString('|', $test); $actual = explode('|', $test); $expected = [ "//div[@id='foo']//span[contains(concat(' ', normalize-space(@class), ' '), ' bar ')]", @@ -86,7 +86,7 @@ public function testMultipleComplexCssSpecificationShouldTransformToExpectedXpat public function testClassNotationWithoutSpecifiedTagShouldResultInMultipleQueries() { $test = Query::cssToXpath('div.foo .bar a .baz span'); - $this->assertContains('|', $test); + $this->assertStringContainsString('|', $test); // @codingStandardsIgnoreStart $segments = [ "//div[contains(concat(' ', normalize-space(@class), ' '), ' foo ')]//*[contains(concat(' ', normalize-space(@class), ' '), ' bar ')]//a//*[contains(concat(' ', normalize-space(@class), ' '), ' baz ')]//span", @@ -96,7 +96,7 @@ public function testClassNotationWithoutSpecifiedTagShouldResultInMultipleQuerie ]; // @codingStandardsIgnoreEnd foreach ($segments as $xpath) { - $this->assertContains($xpath, $test); + $this->assertStringContainsString($xpath, $test); } } diff --git a/test/DocumentTest.php b/test/DocumentTest.php index 2227384..b925036 100644 --- a/test/DocumentTest.php +++ b/test/DocumentTest.php @@ -29,10 +29,8 @@ class DocumentTest extends TestCase /** * Sets up the fixture, for example, open a network connection. * This method is called before a test is executed. - * - * @return void */ - public function setUp() + public function setUp(): void { $this->document = new Document(); } @@ -233,17 +231,15 @@ public function testXpathPhpFunctionsShouldBeEnabledWithoutParameter() public function testXpathPhpFunctionsShouldBeNotCalledWhenSpecifiedFunction() { $this->loadHtml(); - try { - $this->document->registerXpathPhpFunctions('stripos'); - $result = Document\Query::execute( - '//meta[php:functionString("strtolower", @http-equiv) = "content-type"]', - $this->document - ); - } catch (\Exception $e) { - // $e->getMessage() - Not allowed to call handler 'strtolower() - return; - } - $this->fail('Not allowed to call handler strtolower()'); + $this->document->registerXpathPhpFunctions('stripos'); + + $this->expectException(\Error::class); + $this->expectExceptionMessage('Not allowed to call handler \'strtolower()\'.'); + + Document\Query::execute( + '//meta[php:functionString("strtolower", @http-equiv) = "content-type"]', + $this->document + ); } /** @@ -255,7 +251,7 @@ public function testLoadingDocumentWithErrorsShouldNotRaisePhpErrors() $this->document = new Document($file); $result = Document\Query::execute('p', $this->document, Document\Query::TYPE_CSS); $errors = $this->document->getErrors(); - $this->assertInternalType('array', $errors); + $this->assertIsArray($errors); $this->assertNotEmpty($errors); } From fb10bce7bfc6768577f832eb8b3566a8db99631a Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 21 Oct 2020 12:12:37 +0200 Subject: [PATCH 03/10] Make tests pass in all PHP version supported Signed-off-by: Filippo Tessarotto --- test/DocumentTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/DocumentTest.php b/test/DocumentTest.php index b925036..d9f6ef8 100644 --- a/test/DocumentTest.php +++ b/test/DocumentTest.php @@ -233,8 +233,8 @@ public function testXpathPhpFunctionsShouldBeNotCalledWhenSpecifiedFunction() $this->loadHtml(); $this->document->registerXpathPhpFunctions('stripos'); - $this->expectException(\Error::class); - $this->expectExceptionMessage('Not allowed to call handler \'strtolower()\'.'); + $this->expectException(PHP_VERSION_ID >= 80000 ? \Error::class : \ErrorException::class); + $this->expectExceptionMessageMatches('/Not allowed to call handler .strtolower()/'); Document\Query::execute( '//meta[php:functionString("strtolower", @http-equiv) = "content-type"]', From fc037f0b9805d2606c4544fa955e2bed588aa4e4 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 21 Oct 2020 12:42:31 +0200 Subject: [PATCH 04/10] Travis: test against PHP 8.0 Signed-off-by: Filippo Tessarotto --- .travis.yml | 24 ++++++------------------ composer.json | 2 +- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index d63ede4..2bb479a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,36 +12,24 @@ env: matrix: fast_finish: true include: - - php: 5.6 - env: - - DEPS=lowest - - php: 5.6 - env: - - DEPS=latest - - php: 7 - env: - - DEPS=lowest - - php: 7 - env: - - DEPS=latest - - php: 7.1 + - php: 7.3 env: - DEPS=lowest - - php: 7.1 + - php: 7.3 env: - DEPS=latest - CS_CHECK=true - TEST_COVERAGE=true - - php: 7.2 + - php: 7.4 env: - DEPS=lowest - - php: 7.2 + - php: 7.4 env: - DEPS=latest - - php: 7.3 + - php: nightly env: - DEPS=lowest - - php: 7.3 + - php: nightly env: - DEPS=latest diff --git a/composer.json b/composer.json index a23eb6e..e677562 100644 --- a/composer.json +++ b/composer.json @@ -26,7 +26,7 @@ }, "require": { "php": "^7.3 || ~8.0.0", - "laminas/laminas-zendframework-bridge": "^1.0" + "laminas/laminas-zendframework-bridge": "^1.1" }, "require-dev": { "laminas/laminas-coding-standard": "~1.0.0", From e82a765e98de1521d8255bc0811ef7414d9974a9 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Wed, 21 Oct 2020 13:19:49 +0200 Subject: [PATCH 05/10] LibXML prior to 2.9 must keep libxml_disable_entity_loader Signed-off-by: Filippo Tessarotto --- src/Document.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Document.php b/src/Document.php index aa78e56..91d11a1 100644 --- a/src/Document.php +++ b/src/Document.php @@ -231,6 +231,9 @@ protected function setErrors($errors) protected function getDomDocumentFromString($stringDocument) { libxml_use_internal_errors(true); + if (LIBXML_VERSION < 20900) { + libxml_disable_entity_loader(true); + } $encoding = $this->getEncoding(); $domDoc = null === $encoding ? new DOMDocument('1.0') : new DOMDocument('1.0', $encoding); @@ -260,6 +263,9 @@ protected function getDomDocumentFromString($stringDocument) libxml_clear_errors(); } + if (LIBXML_VERSION < 20900) { + libxml_disable_entity_loader(false); + } libxml_use_internal_errors(false); if (! $success) { From 4717ae349c4ec45300b5e82dc9eb5278619786f5 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Mon, 2 Nov 2020 08:48:30 +0100 Subject: [PATCH 06/10] Avoid libxml check duplication Signed-off-by: Filippo Tessarotto --- src/Document.php | 26 ++++++++++++++++++++------ src/Query.php | 4 ++-- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/Document.php b/src/Document.php index 91d11a1..3aafc2c 100644 --- a/src/Document.php +++ b/src/Document.php @@ -231,9 +231,7 @@ protected function setErrors($errors) protected function getDomDocumentFromString($stringDocument) { libxml_use_internal_errors(true); - if (LIBXML_VERSION < 20900) { - libxml_disable_entity_loader(true); - } + $disableEntityLoaderFlag = self::disableEntityLoader(); $encoding = $this->getEncoding(); $domDoc = null === $encoding ? new DOMDocument('1.0') : new DOMDocument('1.0', $encoding); @@ -263,9 +261,7 @@ protected function getDomDocumentFromString($stringDocument) libxml_clear_errors(); } - if (LIBXML_VERSION < 20900) { - libxml_disable_entity_loader(false); - } + self::disableEntityLoader($disableEntityLoaderFlag); libxml_use_internal_errors(false); if (! $success) { @@ -315,4 +311,22 @@ public function registerXpathPhpFunctions($xpathPhpFunctions = true) { $this->xpathPhpFunctions = $xpathPhpFunctions; } + + /** + * Disable the ability to load external XML entities based on libxml version + * + * If we are using libxml < 2.9, unsafe XML entity loading must be + * disabled with a flag. + * + * If we are using libxml >= 2.9, XML entity loading is disabled by default. + * + * @return bool + */ + public static function disableEntityLoader($flag = true) + { + if (LIBXML_VERSION < 20900) { + return libxml_disable_entity_loader($flag); + } + return $flag; + } } diff --git a/src/Query.php b/src/Query.php index b6bb791..6d5560d 100644 --- a/src/Query.php +++ b/src/Query.php @@ -232,7 +232,7 @@ public function queryXpath($xpathQuery, $query = null, DOMNode $contextNode = nu $encoding = $this->getEncoding(); libxml_use_internal_errors(true); - libxml_disable_entity_loader(true); + $disableEntityLoaderFlag = Document::disableEntityLoader(); if (null === $encoding) { $domDoc = new DOMDocument('1.0'); } else { @@ -261,7 +261,7 @@ public function queryXpath($xpathQuery, $query = null, DOMNode $contextNode = nu $this->documentErrors = $errors; libxml_clear_errors(); } - libxml_disable_entity_loader(false); + Document::disableEntityLoader($disableEntityLoaderFlag); libxml_use_internal_errors(false); if (! $success) { From a62aa068efa57a8a680ab99ef63f1a05d6d5d03e Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Mon, 2 Nov 2020 08:48:54 +0100 Subject: [PATCH 07/10] Explicit ext-dom and ext-libxml requirements Signed-off-by: Filippo Tessarotto --- composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/composer.json b/composer.json index e677562..02e6b93 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,8 @@ }, "require": { "php": "^7.3 || ~8.0.0", + "ext-dom": "*", + "ext-libxml": "*", "laminas/laminas-zendframework-bridge": "^1.1" }, "require-dev": { From c33652fe792e2d583c4a3fc0d308e1edac313e8f Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 12 Nov 2020 10:23:19 +0100 Subject: [PATCH 08/10] Make disableEntityLoader private Signed-off-by: Filippo Tessarotto --- .gitignore | 1 + composer.json | 2 +- src/Document.php | 2 +- src/Query.php | 22 ++++++++++++++++++++-- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 87904ec..f2b1db6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ /docs/html/ /laminas-mkdoc-theme.tgz /laminas-mkdoc-theme/ +/.phpunit.result.cache /phpunit.xml /vendor/ diff --git a/composer.json b/composer.json index 02e6b93..f2437f0 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ }, "require-dev": { "laminas/laminas-coding-standard": "~1.0.0", - "phpunit/phpunit": "^9.4.2" + "phpunit/phpunit": "^9.4.3" }, "autoload": { "psr-4": { diff --git a/src/Document.php b/src/Document.php index 3aafc2c..41d6b24 100644 --- a/src/Document.php +++ b/src/Document.php @@ -322,7 +322,7 @@ public function registerXpathPhpFunctions($xpathPhpFunctions = true) * * @return bool */ - public static function disableEntityLoader($flag = true) + private static function disableEntityLoader($flag = true) { if (LIBXML_VERSION < 20900) { return libxml_disable_entity_loader($flag); diff --git a/src/Query.php b/src/Query.php index 6d5560d..ecbff61 100644 --- a/src/Query.php +++ b/src/Query.php @@ -232,7 +232,7 @@ public function queryXpath($xpathQuery, $query = null, DOMNode $contextNode = nu $encoding = $this->getEncoding(); libxml_use_internal_errors(true); - $disableEntityLoaderFlag = Document::disableEntityLoader(); + $disableEntityLoaderFlag = self::disableEntityLoader(); if (null === $encoding) { $domDoc = new DOMDocument('1.0'); } else { @@ -261,7 +261,7 @@ public function queryXpath($xpathQuery, $query = null, DOMNode $contextNode = nu $this->documentErrors = $errors; libxml_clear_errors(); } - Document::disableEntityLoader($disableEntityLoaderFlag); + self::disableEntityLoader($disableEntityLoaderFlag); libxml_use_internal_errors(false); if (! $success) { @@ -320,4 +320,22 @@ protected function getNodeList($document, $xpathQuery, DOMNode $contextNode = nu $nodeList = $xpath->queryWithErrorException($xpathQuery, $contextNode); return $nodeList; } + + /** + * Disable the ability to load external XML entities based on libxml version + * + * If we are using libxml < 2.9, unsafe XML entity loading must be + * disabled with a flag. + * + * If we are using libxml >= 2.9, XML entity loading is disabled by default. + * + * @return bool + */ + private static function disableEntityLoader($flag = true) + { + if (LIBXML_VERSION < 20900) { + return libxml_disable_entity_loader($flag); + } + return $flag; + } } From 3b9c28968d8146a8cf31be66f013716d865bd260 Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Thu, 12 Nov 2020 10:25:13 +0100 Subject: [PATCH 09/10] Migrate PHPUnit configuration Signed-off-by: Filippo Tessarotto --- phpunit.xml.dist | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9fbc2cf..93d33cc 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,17 +1,16 @@ - - - ./test - - - - - - ./src - - + xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" + bootstrap="vendor/autoload.php" + colors="true"> + + + ./src + + + + + ./test + + From 2b668b8bc91647d447708450b1a018460709b97b Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Mon, 11 Jan 2021 14:01:08 +0100 Subject: [PATCH 10/10] Use PHP `8.0` instead of `nightly` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ref: https://github.com/laminas/laminas-dom/pull/8/files#r555016095 Ref: https://github.com/laminas/laminas-dom/pull/8/files#r555015886 Co-authored-by: Frank Brückner --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2bb479a..677679f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,10 +26,10 @@ matrix: - php: 7.4 env: - DEPS=latest - - php: nightly + - php: 8.0 env: - DEPS=lowest - - php: nightly + - php: 8.0 env: - DEPS=latest