From e6444bb57e60d56648ea60cf6b30f737c052e2c1 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 10:42:29 +0000
Subject: [PATCH 1/6] Add unsafeHtml option for extensions to use on trusted
input
---
Parsedown.php | 21 +++++++++++++++++++--
test/ParsedownTest.php | 12 ++++++++++++
test/UnsafeExtension.php | 14 ++++++++++++++
3 files changed, 45 insertions(+), 2 deletions(-)
create mode 100644 test/UnsafeExtension.php
diff --git a/Parsedown.php b/Parsedown.php
index 2725170..b274f52 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1488,7 +1488,20 @@ class Parsedown
}
}
+ $unsafeHtml = false;
if (isset($Element['text']))
+ {
+ $text = $Element['text'];
+ }
+ // very strongly consider an alternative if you're writing an
+ // extension
+ elseif (isset($Element['unsafeHtml']) and !$this->safeMode)
+ {
+ $text = $Element['unsafeHtml'];
+ $unsafeHtml = true;
+ }
+
+ if (isset($text))
{
$markup .= $hasName ? '>' : '';
@@ -1499,11 +1512,15 @@ class Parsedown
if (isset($Element['handler']))
{
- $markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
+ $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
+ }
+ elseif ($unsafeHtml !== true or $this->safeMode)
+ {
+ $markup .= self::escape($text, true);
}
else
{
- $markup .= self::escape($Element['text'], true);
+ $markup .= $text;
}
$markup .= $hasName ? ''.$Element['name'].'>' : '';
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index c28cedf..3cd796e 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,4 +1,5 @@
assertEquals($expectedMarkup, $actualMarkup);
}
+ function testUnsafeHtml()
+ {
+ $markdown = "```php\nfoobar\n```";
+ $expectedMarkup = 'foobar
';
+
+ $unsafeExtension = new UnsafeExtension;
+ $actualMarkup = $unsafeExtension->text($markdown);
+
+ $this->assertEquals($expectedMarkup, $actualMarkup);
+ }
+
function data()
{
$data = array();
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
new file mode 100644
index 0000000..f2343c4
--- /dev/null
+++ b/test/UnsafeExtension.php
@@ -0,0 +1,14 @@
+$text
";
+
+ return $Block;
+ }
+}
From e4c5be026d4c776261edf5e8ef802e258bfaee9f Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 11:00:03 +0000
Subject: [PATCH 2/6] Further attempt to dissuade this feature's use
---
test/UnsafeExtension.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
index f2343c4..9a8dcc7 100644
--- a/test/UnsafeExtension.php
+++ b/test/UnsafeExtension.php
@@ -7,6 +7,11 @@ class UnsafeExtension extends Parsedown
$text = $Block['element']['text']['text'];
unset($Block['element']['text']['text']);
+ // WARNING: There is almost always a better way of doing things!
+ //
+ // This example is one of them, unsafe behaviour is NOT needed here.
+ // Only use this if you trust the input and have no idea what
+ // the output HTML will look like (e.g. using an external parser).
$Block['element']['text']['unsafeHtml'] = "$text
";
return $Block;
From ef7ed7b66cf22b268c459a98e4fe3f7f809d40b5 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 11:09:55 +0000
Subject: [PATCH 3/6] Still grab the text if safe mode enabled, but output it
escaped
---
Parsedown.php | 3 ++-
test/ParsedownTest.php | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Parsedown.php b/Parsedown.php
index b274f52..9558525 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1495,9 +1495,10 @@ class Parsedown
}
// very strongly consider an alternative if you're writing an
// extension
- elseif (isset($Element['unsafeHtml']) and !$this->safeMode)
+ elseif (isset($Element['unsafeHtml']))
{
$text = $Element['unsafeHtml'];
+
$unsafeHtml = true;
}
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 3cd796e..8f3e6c8 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -60,11 +60,17 @@ class ParsedownTest extends TestCase
{
$markdown = "```php\nfoobar\n```";
$expectedMarkup = 'foobar
';
+ $expectedSafeMarkup = '<p>foobar</p>
';
$unsafeExtension = new UnsafeExtension;
$actualMarkup = $unsafeExtension->text($markdown);
$this->assertEquals($expectedMarkup, $actualMarkup);
+
+ $unsafeExtension->setSafeMode(true);
+ $actualSafeMarkup = $unsafeExtension->text($markdown);
+
+ $this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
}
function data()
From 3fc54bc966caea29a633dba41ebb6728a917ee67 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 19:46:03 +0000
Subject: [PATCH 4/6] Allow extension to "vouch" for raw HTML they produce
Rename "unsafeHtml" to "rawHtml"
---
Parsedown.php | 25 ++++++++++++++++++++-----
test/ParsedownTest.php | 21 +++++++++++++++++++--
test/SampleExtensions.php | 39 +++++++++++++++++++++++++++++++++++++++
test/UnsafeExtension.php | 19 -------------------
4 files changed, 78 insertions(+), 26 deletions(-)
create mode 100644 test/SampleExtensions.php
delete mode 100644 test/UnsafeExtension.php
diff --git a/Parsedown.php b/Parsedown.php
index 9558525..160594e 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1488,18 +1488,33 @@ class Parsedown
}
}
- $unsafeHtml = false;
+ $permitRawHtml = false;
+
if (isset($Element['text']))
{
$text = $Element['text'];
}
// very strongly consider an alternative if you're writing an
// extension
- elseif (isset($Element['unsafeHtml']))
+ elseif (isset($Element['rawHtml']))
{
- $text = $Element['unsafeHtml'];
+ $text = $Element['rawHtml'];
- $unsafeHtml = true;
+ $allowRawHtmlInSafeMode = false;
+
+ if (isset($Element['allowRawHtmlInSafeMode']))
+ {
+ $allowRawHtmlInSafeMode = (true === $Element['allowRawHtmlInSafeMode']);
+ }
+
+ if ($this->safeMode !== true)
+ {
+ $permitRawHtml = true;
+ }
+ elseif ($this->safeMode and $allowRawHtmlInSafeMode)
+ {
+ $permitRawHtml = true;
+ }
}
if (isset($text))
@@ -1515,7 +1530,7 @@ class Parsedown
{
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
}
- elseif ($unsafeHtml !== true or $this->safeMode)
+ elseif ($permitRawHtml !== true)
{
$markup .= self::escape($text, true);
}
diff --git a/test/ParsedownTest.php b/test/ParsedownTest.php
index 8f3e6c8..cc0cc1d 100644
--- a/test/ParsedownTest.php
+++ b/test/ParsedownTest.php
@@ -1,5 +1,5 @@
assertEquals($expectedMarkup, $actualMarkup);
}
- function testUnsafeHtml()
+ function testRawHtml()
{
$markdown = "```php\nfoobar\n```";
$expectedMarkup = 'foobar
';
@@ -73,6 +73,23 @@ class ParsedownTest extends TestCase
$this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
}
+ function testTrustDelegatedRawHtml()
+ {
+ $markdown = "```php\nfoobar\n```";
+ $expectedMarkup = 'foobar
';
+ $expectedSafeMarkup = $expectedMarkup;
+
+ $unsafeExtension = new TrustDelegatedExtension;
+ $actualMarkup = $unsafeExtension->text($markdown);
+
+ $this->assertEquals($expectedMarkup, $actualMarkup);
+
+ $unsafeExtension->setSafeMode(true);
+ $actualSafeMarkup = $unsafeExtension->text($markdown);
+
+ $this->assertEquals($expectedSafeMarkup, $actualSafeMarkup);
+ }
+
function data()
{
$data = array();
diff --git a/test/SampleExtensions.php b/test/SampleExtensions.php
new file mode 100644
index 0000000..6d7ec9f
--- /dev/null
+++ b/test/SampleExtensions.php
@@ -0,0 +1,39 @@
+$text";
+
+ return $Block;
+ }
+}
+
+
+class TrustDelegatedExtension extends Parsedown
+{
+ protected function blockFencedCodeComplete($Block)
+ {
+ $text = $Block['element']['text']['text'];
+ unset($Block['element']['text']['text']);
+
+ // WARNING: There is almost always a better way of doing things!
+ //
+ // This example is one of them, unsafe behaviour is NOT needed here.
+ // Only use this if you trust the input and have no idea what
+ // the output HTML will look like (e.g. using an external parser).
+ $Block['element']['text']['rawHtml'] = "$text
";
+ $Block['element']['text']['allowRawHtmlInSafeMode'] = true;
+
+ return $Block;
+ }
+}
diff --git a/test/UnsafeExtension.php b/test/UnsafeExtension.php
deleted file mode 100644
index 9a8dcc7..0000000
--- a/test/UnsafeExtension.php
+++ /dev/null
@@ -1,19 +0,0 @@
-$text";
-
- return $Block;
- }
-}
From 624a08b7eb8c3a4b0b99e7175251b76483e387cf Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Thu, 15 Mar 2018 19:55:33 +0000
Subject: [PATCH 5/6] Update commment
---
test/SampleExtensions.php | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/test/SampleExtensions.php b/test/SampleExtensions.php
index 6d7ec9f..c66190c 100644
--- a/test/SampleExtensions.php
+++ b/test/SampleExtensions.php
@@ -28,9 +28,10 @@ class TrustDelegatedExtension extends Parsedown
// WARNING: There is almost always a better way of doing things!
//
- // This example is one of them, unsafe behaviour is NOT needed here.
- // Only use this if you trust the input and have no idea what
- // the output HTML will look like (e.g. using an external parser).
+ // This behaviour is NOT needed in the demonstrated case.
+ // Only use this if you are sure that the result being added into
+ // rawHtml is safe.
+ // (e.g. using an external parser with escaping capabilities).
$Block['element']['text']['rawHtml'] = "$text
";
$Block['element']['text']['allowRawHtmlInSafeMode'] = true;
From 88dc94989039d37e09f186e94ec3a3964af82b36 Mon Sep 17 00:00:00 2001
From: Aidan Woods
Date: Sun, 18 Mar 2018 19:42:14 +0000
Subject: [PATCH 6/6] Refactor based on suggestion by @PhrozenByte
---
Parsedown.php | 19 +++----------------
1 file changed, 3 insertions(+), 16 deletions(-)
diff --git a/Parsedown.php b/Parsedown.php
index 160594e..bf08700 100644
--- a/Parsedown.php
+++ b/Parsedown.php
@@ -1500,21 +1500,8 @@ class Parsedown
{
$text = $Element['rawHtml'];
- $allowRawHtmlInSafeMode = false;
-
- if (isset($Element['allowRawHtmlInSafeMode']))
- {
- $allowRawHtmlInSafeMode = (true === $Element['allowRawHtmlInSafeMode']);
- }
-
- if ($this->safeMode !== true)
- {
- $permitRawHtml = true;
- }
- elseif ($this->safeMode and $allowRawHtmlInSafeMode)
- {
- $permitRawHtml = true;
- }
+ $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
+ $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
}
if (isset($text))
@@ -1530,7 +1517,7 @@ class Parsedown
{
$markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
}
- elseif ($permitRawHtml !== true)
+ elseif (!$permitRawHtml)
{
$markup .= self::escape($text, true);
}