Skip to content

Commit acb0fa0

Browse files
authored
IBX-8891: Fixed XML link validation to allow using tel: in links (#245)
* IBX-8891: XML link validator in rich-text does not allow to use "tel: " * [PHPStan] Aligned baseline after PHPStan update
1 parent dbe816f commit acb0fa0

File tree

4 files changed

+94
-29
lines changed

4 files changed

+94
-29
lines changed

phpstan-baseline.neon

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,36 @@ parameters:
625625
count: 1
626626
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
627627

628+
-
629+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: ''\\|'ezremote\\://', 2\\?\\: string, 3\\?\\: string\\}\\.$#"
630+
count: 1
631+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
632+
633+
-
634+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: string, 2\\?\\: string\\}\\.$#"
635+
count: 1
636+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
637+
638+
-
639+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\: 'ezremote\\://', 2\\?\\: string, 3\\?\\: string\\}\\.$#"
640+
count: 1
641+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
642+
643+
-
644+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\?\\: ''\\|'ezremote\\://', 2\\?\\: string, 3\\?\\: string\\}\\.$#"
645+
count: 2
646+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
647+
648+
-
649+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\?\\: string, 2\\?\\: string\\}\\.$#"
650+
count: 1
651+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
652+
653+
-
654+
message: "#^Offset 3 does not exist on array\\{0\\?\\: string, 1\\?\\: ''\\|'ezremote\\://', 2\\?\\: string, 3\\?\\: string\\}\\.$#"
655+
count: 1
656+
path: src/lib/eZ/FieldType/RichText/RichTextStorage.php
657+
628658
-
629659
message: "#^Parameter \\#1 \\$source of method DOMDocument\\:\\:loadXML\\(\\) expects string, array\\|bool\\|float\\|int\\|string\\|null given\\.$#"
630660
count: 2
@@ -770,6 +800,21 @@ parameters:
770800
count: 4
771801
path: src/lib/eZ/RichText/Converter/Link.php
772802

803+
-
804+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
805+
count: 1
806+
path: src/lib/eZ/RichText/Converter/Link.php
807+
808+
-
809+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\?\\: string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
810+
count: 1
811+
path: src/lib/eZ/RichText/Converter/Link.php
812+
813+
-
814+
message: "#^Offset 3 does not exist on array\\{0\\?\\: string, 1\\?\\: string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
815+
count: 1
816+
path: src/lib/eZ/RichText/Converter/Link.php
817+
773818
-
774819
message: "#^Parameter \\#1 \\$locationId of method eZ\\\\Publish\\\\API\\\\Repository\\\\LocationService\\:\\:loadLocation\\(\\) expects int, int\\|null given\\.$#"
775820
count: 1
@@ -915,6 +960,21 @@ parameters:
915960
count: 1
916961
path: src/lib/eZ/RichText/Converter/Render/Embed.php
917962

963+
-
964+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: 'ezcontent'\\|'ezlocation', 2\\?\\: numeric\\-string\\}\\.$#"
965+
count: 1
966+
path: src/lib/eZ/RichText/Converter/Render/Embed.php
967+
968+
-
969+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\: 'ezcontent', 2\\?\\: numeric\\-string\\}\\.$#"
970+
count: 1
971+
path: src/lib/eZ/RichText/Converter/Render/Embed.php
972+
973+
-
974+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\: 'ezlocation', 2\\?\\: numeric\\-string\\}\\.$#"
975+
count: 1
976+
path: src/lib/eZ/RichText/Converter/Render/Embed.php
977+
918978
-
919979
message: "#^PHPDoc tag @var has invalid value \\(\\$embed \\\\DOMElement\\)\\: Unexpected token \"\\$embed\", expected type at offset 9$#"
920980
count: 1
@@ -1105,6 +1165,16 @@ parameters:
11051165
count: 1
11061166
path: src/lib/eZ/RichText/RelationProcessor.php
11071167

1168+
-
1169+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: non\\-empty\\-string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
1170+
count: 1
1171+
path: src/lib/eZ/RichText/RelationProcessor.php
1172+
1173+
-
1174+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\?\\: non\\-empty\\-string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
1175+
count: 1
1176+
path: src/lib/eZ/RichText/RelationProcessor.php
1177+
11081178
-
11091179
message: "#^Method EzSystems\\\\EzPlatformRichText\\\\eZ\\\\RichText\\\\RendererInterface\\:\\:renderContentEmbed\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#"
11101180
count: 1
@@ -1150,6 +1220,16 @@ parameters:
11501220
count: 1
11511221
path: src/lib/eZ/RichText/Validator/InternalLinkValidator.php
11521222

1223+
-
1224+
message: "#^Offset 1 does not exist on array\\{0\\?\\: string, 1\\?\\: non\\-empty\\-string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
1225+
count: 1
1226+
path: src/lib/eZ/RichText/Validator/InternalLinkValidator.php
1227+
1228+
-
1229+
message: "#^Offset 2 does not exist on array\\{0\\?\\: string, 1\\?\\: non\\-empty\\-string, 2\\?\\: string, 3\\?\\: string\\}\\.$#"
1230+
count: 1
1231+
path: src/lib/eZ/RichText/Validator/InternalLinkValidator.php
1232+
11531233
-
11541234
message: "#^Parameter \\#1 \\$locationId of method eZ\\\\Publish\\\\SPI\\\\Persistence\\\\Content\\\\Location\\\\Handler\\:\\:load\\(\\) expects int, string given\\.$#"
11551235
count: 1
@@ -1629,10 +1709,7 @@ parameters:
16291709
message: "#^Cannot access property \\$id on eZ\\\\Publish\\\\API\\\\Repository\\\\Values\\\\Content\\\\Field\\|null\\.$#"
16301710
count: 1
16311711
path: tests/integration/eZ/API/RichTextFieldTypeIntegrationTest.php
1632-
-
1633-
message: "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\ForwardCompatibility\\\\Result\\|int\\|string\\.$#"
1634-
count: 1
1635-
path: tests/integration/eZ/API/RichTextFieldTypeIntegrationTest.php
1712+
16361713
-
16371714
message: "#^Cannot access property \\$value on eZ\\\\Publish\\\\API\\\\Repository\\\\Values\\\\Content\\\\Field\\|null\\.$#"
16381715
count: 1
@@ -1648,6 +1725,11 @@ parameters:
16481725
count: 1
16491726
path: tests/integration/eZ/API/RichTextFieldTypeIntegrationTest.php
16501727

1728+
-
1729+
message: "#^Cannot call method fetchOne\\(\\) on Doctrine\\\\DBAL\\\\ForwardCompatibility\\\\Result\\|int\\|string\\.$#"
1730+
count: 1
1731+
path: tests/integration/eZ/API/RichTextFieldTypeIntegrationTest.php
1732+
16511733
-
16521734
message: "#^Method EzSystems\\\\IntegrationTests\\\\EzPlatformRichText\\\\eZ\\\\API\\\\RichTextFieldTypeIntegrationTest\\:\\:__construct\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#"
16531735
count: 1

src/lib/eZ/RichText/Resources/schemas/docbook/docbook.iso.sch

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,13 @@
253253
<s:let name="lowerCase" value="'abcdefghijklmnopqrstuvwxyz'"/>
254254
<s:rule context="db:link">
255255
<!-- Using translate() because we don't have XPath 2, so we can't use lower-case(). -->
256-
<s:assert test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http://') or
257-
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'https://') or
256+
<s:assert test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http') or
258257
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'mailto:') or
259-
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezcontent://') or
260-
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezlocation://') or
261-
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezremote://') or
262-
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezurl://') or
258+
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'tel:') or
259+
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ez') or
263260
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '/') or
264261
starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '#')"
265-
mode="schematron-get-full-path-2">links must start with one of: http://, https://, mailto:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #</s:assert>
266-
<s:assert test="not(contains(@*[name()='xlink:href'], '&lt;') or
267-
contains(@*[name()='xlink:href'], '&gt;') or
268-
contains(@*[name()='xlink:href'], '&quot;'))"
269-
mode="schematron-get-full-path-2">using characters [&lt; &gt; &quot;] in links is not allowed</s:assert>
262+
mode="schematron-get-full-path-2">links must start with one of: http://, https://, mailto:, tel:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #</s:assert>
270263
</s:rule>
271264
</s:pattern>
272265
</s:schema>

src/lib/eZ/RichText/Resources/schemas/docbook/docbook.iso.sch.xsl

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,4 @@
7979
<axsl:template match="db:link" priority="1000" mode="M3"><svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" context="db:link"/>
8080

8181
<!--ASSERT -->
82-
<axsl:choose><axsl:when test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'https://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'mailto:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezcontent://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezlocation://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezremote://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezurl://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '/') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '#')"/><axsl:otherwise><svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'https://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'mailto:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezcontent://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezlocation://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezremote://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ezurl://') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '/') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '#')"><axsl:attribute name="location"><axsl:apply-templates select="." mode="schematron-get-full-path-2"/></axsl:attribute><svrl:text>links must start with one of: http://, https://, mailto:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #</svrl:text></svrl:failed-assert></axsl:otherwise></axsl:choose>
83-
84-
<!--ASSERT -->
85-
<axsl:choose><axsl:when test="not(contains(@*[name()='xlink:href'], '&lt;') or contains(@*[name()='xlink:href'], '&gt;') or contains(@*[name()='xlink:href'], '&quot;'))"/><axsl:otherwise><svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" test="not(contains(@*[name()='xlink:href'], '&lt;') or contains(@*[name()='xlink:href'], '&gt;') or contains(@*[name()='xlink:href'], '&quot;'))"><axsl:attribute name="location"><axsl:apply-templates select="." mode="schematron-get-full-path-2"/></axsl:attribute><svrl:text>using characters [&lt; &gt; "] in links is not allowed</svrl:text></svrl:failed-assert></axsl:otherwise></axsl:choose><axsl:apply-templates select="*|comment()|processing-instruction()" mode="M3"/></axsl:template><axsl:template match="text()" priority="-1" mode="M3"/><axsl:template match="@*|node()" priority="-2" mode="M3"><axsl:apply-templates select="*|comment()|processing-instruction()" mode="M3"/></axsl:template></axsl:stylesheet>
82+
<axsl:choose><axsl:when test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'mailto:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'tel:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ez') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '/') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '#')"/><axsl:otherwise><svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" test="starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'http') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'mailto:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'tel:') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), 'ez') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '/') or starts-with(translate(@*[name()='xlink:href'], $upperCase, $lowerCase), '#')"><axsl:attribute name="location"><axsl:apply-templates select="." mode="schematron-get-full-path-2"/></axsl:attribute><svrl:text>links must start with one of: http://, https://, mailto:, tel:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #</svrl:text></svrl:failed-assert></axsl:otherwise></axsl:choose><axsl:apply-templates select="*|comment()|processing-instruction()" mode="M3"/></axsl:template><axsl:template match="text()" priority="-1" mode="M3"/><axsl:template match="@*|node()" priority="-2" mode="M3"><axsl:apply-templates select="*|comment()|processing-instruction()" mode="M3"/></axsl:template></axsl:stylesheet>

tests/lib/eZ/FieldType/RichTextTest.php

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public function providerForTestValidate()
224224
[
225225
new ValidationError(
226226
"Validation of XML content failed:\n" .
227-
'/section/para/link: links must start with one of: http://, https://, mailto:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
227+
'/section/para/link: links must start with one of: http://, https://, mailto:, tel:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
228228
null,
229229
[],
230230
'xml'
@@ -239,7 +239,7 @@ public function providerForTestValidate()
239239
[
240240
new ValidationError(
241241
"Validation of XML content failed:\n" .
242-
'/section/para/link: links must start with one of: http://, https://, mailto:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
242+
'/section/para/link: links must start with one of: http://, https://, mailto:, tel:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
243243
null,
244244
[],
245245
'xml'
@@ -252,13 +252,6 @@ public function providerForTestValidate()
252252
<para><link xlink:href="https://example.com/foo&lt;bar">link</link></para>
253253
</section>',
254254
[
255-
new ValidationError(
256-
"Validation of XML content failed:\n" .
257-
'/section/para/link: using characters [< > "] in links is not allowed',
258-
null,
259-
[],
260-
'xml'
261-
),
262255
],
263256
],
264257
[
@@ -269,7 +262,7 @@ public function providerForTestValidate()
269262
[
270263
new ValidationError(
271264
"Validation of XML content failed:\n" .
272-
'/section/para/link: links must start with one of: http://, https://, mailto:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
265+
'/section/para/link: links must start with one of: http://, https://, mailto:, tel:, ezcontent://, ezlocation://, ezremote://, ezurl://, /, #',
273266
null,
274267
[],
275268
'xml'

0 commit comments

Comments
 (0)