diff --git a/app/logical/d_text.rb b/app/logical/d_text.rb
index de90e2ebd..cd7524e57 100644
--- a/app/logical/d_text.rb
+++ b/app/logical/d_text.rb
@@ -11,15 +11,30 @@ class DText
end
def self.parse_inline(str, options = {})
+ str.gsub!(/&/, "&")
+ str.gsub!(/, "<")
+ str.gsub!(/>/, ">")
str.gsub!(/\n/m, "
")
str.gsub!(/\[b\](.+?)\[\/b\]/i, '\1')
str.gsub!(/\[i\](.+?)\[\/i\]/i, '\1')
- str.gsub!(/\[spoilers?\](.+?)\[\/spoilers?\]/m, '\1')
- str.gsub!(/\[url\](.+?)\[\/url\]/i) do
- %{#{h($1)}}
+ str.gsub!(/(?' + text + '' + stop
end
- str.gsub!(/\[url=(.+?)\](.+?)\[\/url\]/m) do
- %{#{h($2)}}
+ str.gsub!(/\[url\](http.+?)\[\/url\]/i) do
+ %{#{$1}}
+ end
+ str.gsub!(/\[url=(http.+?)\](.+?)\[\/url\]/m) do
+ %{#{$2}}
end
str = parse_aliased_wiki_links(str)
str = parse_wiki_links(str)
@@ -30,33 +45,36 @@ class DText
def self.parse_aliased_wiki_links(str)
str.gsub(/\[\[(.+?)\|(.+?)\]\]/m) do
- text = $1
- title = $2
+ text = CGI.unescapeHTML($1)
+ title = CGI.unescapeHTML($2)
wiki_page = WikiPage.find_title_and_id(title)
if wiki_page
- %{#{text}}
+ %{#{h(text)}}
else
- %{#{text}}
+ %{#{h(text)}}
end
end
end
def self.parse_wiki_links(str)
str.gsub(/\[\[(.+?)\]\]/) do
- title = $1
+ title = CGI.unescapeHTML($1)
wiki_page = WikiPage.find_title_and_id(title)
if wiki_page
- %{#{title}}
+ %{#{h(title)}}
else
- %{#{title}}
+ %{#{h(title)}}
end
end
end
def self.parse_post_links(str)
- str.gsub(/\{\{(.+?)\}\}/, %{\\1})
+ str.gsub(/\{\{(.+?)\}\}/) do
+ tags = CGI.unescapeHTML($1)
+ %{#{h(tags)}}
+ end
end
def self.parse_id_links(str)
@@ -110,11 +128,14 @@ class DText
unless options[:inline]
str.gsub!(/\s*\[quote\]\s*/m, "\n\n[quote]\n\n")
str.gsub!(/\s*\[\/quote\]\s*/m, "\n\n[/quote]\n\n")
+ str.gsub!(/\s*\[spoilers?\](?!\])\s*/m, "\n\n[spoiler]\n\n")
+ str.gsub!(/\s*\[\/spoilers?\]\s*/m, "\n\n[/spoiler]\n\n")
end
str.gsub!(/(?:\r?\n){3,}/, "\n\n")
str.strip!
blocks = str.split(/(?:\r?\n){2}/)
+ stack = []
html = blocks.map do |block|
case block
@@ -135,22 +156,57 @@ class DText
if options[:inline]
""
else
- '
' + stack << "blockquote" + "" + elsif tag == "div" + html << "" + end + end - Sanitize.clean(html.join(""), Sanitize::Config::BASIC).html_safe + Sanitize.clean( + html.join(""), + :elements => %w(h1 h2 h3 h4 h5 h6 a span div blockquote br p ul li ol em strong), + :attributes => { + "a" => %w(href title), + "span" => %w(class), + "div" => %w(class) + }, + :protocols => { + "a" => { + "href" => ["http", "https", :relative] + } + } + ).html_safe end end diff --git a/test/unit/dtext_test.rb b/test/unit/dtext_test.rb new file mode 100644 index 000000000..c9a0a0d9b --- /dev/null +++ b/test/unit/dtext_test.rb @@ -0,0 +1,81 @@ +require "test_helper" + +class DTextTest < ActiveSupport::TestCase + def p(s) + DText.parse(s) + end + + def test_sanitize + assert_equal('" end when "[/quote]" if options[:inline] "" - else + elsif stack.last == "blockquote" + stack.pop '' + else + "" + end + + when /\[spoilers?\](?!\])/ + stack << "div" + '' + + when /\[\/spoilers?\]/ + if stack.last == "div" + stack.pop + '' end else '' + parse_inline(block) + "
" end end + + stack.reverse.each do |tag| + if tag == "blockquote" + html << "
<
', p("<")) + assert_equal('>
', p(">")) + assert_equal('&
', p("&")) + end + + def test_wiki_links + assert_equal("a b c
", p("a [[b]] c")) + assert_equal("a spoiler c
", p("a [[spoiler]] c")) + end + + def test_spoilers + assert_equal("this is
an inline spoiler
.
", p("this is [spoiler]an inline spoiler[/spoiler].")) + assert_equal("this is
a block spoiler
.
", p("this is\n\n[spoiler]\na block spoiler\n[/spoiler].")) + end + + def test_paragraphs + assert_equal("a
", p("a")) + assert_equal("abc
", p("abc")) + assert_equal("a
b
c
a
b
", p("a\n\nb")) + end + + def test_headers + assert_equal("paragraph
", p("h1.header\n\nparagraph")) + end + + def test_quote_blocks + assert_equal('', p("[quote]\ntest\n[/quote]")) + assert_equal("test
\n", p("[quote]\na\n[quote]\nb\n[/quote]\nc\n[/quote]")) + end + + def test_urls + assert_equal('a
\n\nb
c
\n
a http://test.com b
', p('a http://test.com b')) + assert_equal('a http://test.com/~bob/image.jpg b
', p('a http://test.com/~bob/image.jpg b')) + assert_equal('a http://test.com/home.html#toc b
', p('a http://test.com/home.html#toc b')) + assert_equal('a http://test.com. b
', p('a http://test.com. b')) + assert_equal('a (http://test.com) b
', p('a (http://test.com) b')) + end + + def test_links + assert_equal('', p('[url=http://test.com]test[/url]')) + assert_equal('"1" 2
', p('"1" [url=http://two.com]2[/url]')) + assert_equal('"1" 2 & 3
', p('"1" [url=http://three.com]2 & 3[/url]')) + end + + def test_aliased_urls + assert_equal('a bob. b
', p('a [url=http://test.com]bob[/url]. b')) + assert_equal('', p('[i][url=http://test.com]bob[/url][/i]')) + end + + def test_lists + assert_equal('testing
testing
a
b
', p("a\n\n\n\n\n\n\nb\n\n\n\n")) + end +end