Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link uri encoding, URL-escaping should be left alone inside the destination #598

Merged
merged 9 commits into from
Mar 19, 2024
29 changes: 18 additions & 11 deletions lib/src/util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,28 @@ String normalizeLinkLabel(String label) {
}

/// Normalizes a link destination, including the process of HTML characters
/// decoding and percent encoding.
/// decoding and percent encoding.
// See the description of these examples:
// https://spec.commonmark.org/0.30/#example-501
// https://spec.commonmark.org/0.30/#example-502
String normalizeLinkDestination(String destination) {
// Decode first, because the destination might have been partly encoded.
// For example https://spec.commonmark.org/0.30/#example-502.
// With this function, `foo%20bä` will be parsed in the following steps:
// 1. foo bä
// 2. foo bä
// 3. foo%20b%C3%A4
try {
destination = Uri.decodeFull(destination);
} catch (_) {}
return Uri.encodeFull(decodeHtmlCharacters(destination));
// Split by url escaping characters
// Concatenate them with unmodified URL-escaping.
// URL-escaping should be left alone inside the destination
// Refer: https://spec.commonmark.org/0.30/#example-502.

final regex = RegExp('%[0-9A-Fa-f]{2}');

return destination.splitMapJoin(
regex,
onMatch: (m) => m.match,
onNonMatch: (e) {
try {
e = Uri.decodeFull(e);
} catch (_) {}
return Uri.encodeFull(decodeHtmlCharacters(e));
},
);
}

/// Normalizes a link title, including the process of HTML characters decoding
Expand Down
6 changes: 5 additions & 1 deletion test/original/inline_images.unit
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@
![Uh oh...]("onerror="alert('XSS'))

<<<
<p><img src="%22onerror=%22alert('XSS')" alt="Uh oh..." /></p>
<p><img src="%22onerror=%22alert('XSS')" alt="Uh oh..." /></p>
>>> URL-escaping should be left alone inside the destination
![](https://example/foo%2Fvar)
<<<
<p><img src="https://example/foo%2Fvar" alt="" /></p>
Loading