From 50a94b6a21456cb6cd86168de20997fabcdeaced Mon Sep 17 00:00:00 2001 From: hanshenrik Date: Wed, 13 Dec 2023 13:21:47 +0100 Subject: [PATCH 1/3] fix xpath php-string-to-javascript-string TL;DR: addslashes() is not the correct way to convert a php-string to a javascript string. json_encode() is. For example, addslashes will fail on the PHP string "foo".chr(10)."bar" , the old addslashes() will convert it into "foo bar" which is a javascript syntax error. Previously this code would fail: $str = "foo".chr(10)."bar"; $xps = new XPathSelector("//span[contains(text(),'" . $str . "')]"); var_dump($xps->expressionCount()); it would generate a javascript syntax error: string(134) "document.evaluate("//span[contains(text(),\'foo bar\')]", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshot Length" now it generates legal javascript: string(135) "document.evaluate("\/\/span[contains(text(),'foo\nbar')]", document , null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength" --- src/Dom/Selector/XPathSelector.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Dom/Selector/XPathSelector.php b/src/Dom/Selector/XPathSelector.php index 5d984def..5d97d965 100644 --- a/src/Dom/Selector/XPathSelector.php +++ b/src/Dom/Selector/XPathSelector.php @@ -19,18 +19,11 @@ public function __construct(string $expression) public function expressionCount(): string { - return \sprintf( - 'document.evaluate("%s", document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength', - \addslashes($this->expression) - ); + return 'document.evaluate('. json_encode($this->expression, JSON_THROW_ON_ERROR) .', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength'; } public function expressionFindOne(int $position): string { - return \sprintf( - 'document.evaluate("%s[%d]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue', - \addslashes($this->expression), - $position - ); + return 'document.evaluate('. json_encode($this->expression . "[{$position}]", JSON_THROW_ON_ERROR) .', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue'; } } From 9f84b7bebd3468326f1fc809e7d51955c490ff7c Mon Sep 17 00:00:00 2001 From: hanshenrik Date: Wed, 13 Dec 2023 13:27:26 +0100 Subject: [PATCH 2/3] styling --- src/Dom/Selector/XPathSelector.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Dom/Selector/XPathSelector.php b/src/Dom/Selector/XPathSelector.php index 5d97d965..d76f55b9 100644 --- a/src/Dom/Selector/XPathSelector.php +++ b/src/Dom/Selector/XPathSelector.php @@ -19,11 +19,11 @@ public function __construct(string $expression) public function expressionCount(): string { - return 'document.evaluate('. json_encode($this->expression, JSON_THROW_ON_ERROR) .', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength'; + return 'document.evaluate('.\json_encode($this->expression, \JSON_THROW_ON_ERROR).', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength'; } public function expressionFindOne(int $position): string { - return 'document.evaluate('. json_encode($this->expression . "[{$position}]", JSON_THROW_ON_ERROR) .', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue'; + return 'document.evaluate('.\json_encode($this->expression."[{$position}]", \JSON_THROW_ON_ERROR).', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue'; } } From c0c0c76dd27b64930179769a4f7d89a0e96667e9 Mon Sep 17 00:00:00 2001 From: hanshenrik Date: Wed, 13 Dec 2023 13:34:02 +0100 Subject: [PATCH 3/3] prettier run-time error messages --- src/Dom/Selector/XPathSelector.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Dom/Selector/XPathSelector.php b/src/Dom/Selector/XPathSelector.php index d76f55b9..71981ee2 100644 --- a/src/Dom/Selector/XPathSelector.php +++ b/src/Dom/Selector/XPathSelector.php @@ -19,11 +19,11 @@ public function __construct(string $expression) public function expressionCount(): string { - return 'document.evaluate('.\json_encode($this->expression, \JSON_THROW_ON_ERROR).', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength'; + return 'document.evaluate('.\json_encode($this->expression, \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE).', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null).snapshotLength'; } public function expressionFindOne(int $position): string { - return 'document.evaluate('.\json_encode($this->expression."[{$position}]", \JSON_THROW_ON_ERROR).', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue'; + return 'document.evaluate('.\json_encode($this->expression."[{$position}]", \JSON_THROW_ON_ERROR | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE).', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue'; } }