diff --git a/lib/chunks/category.rb b/lib/chunks/category.rb
index d08d8636..b35bc484 100644
--- a/lib/chunks/category.rb
+++ b/lib/chunks/category.rb
@@ -16,7 +16,8 @@ class Category < Chunk::Abstract
def initialize(match_data, content)
super(match_data, content)
@hidden = match_data[1]
- @list = match_data[2].split(',').map { |c| c.strip }
+ @list = match_data[2].split(',').map { |c| c.to_s.is_utf8? ? html_escape(c. strip) : nil }
+ @list.compact!
@unmask_text = ''
if @hidden
@unmask_text = ''
@@ -28,6 +29,6 @@ def initialize(match_data, content)
# TODO move presentation of page metadata to controller/view
def url(category)
- %{#{category}}
+ %{#{category}}
end
end
diff --git a/lib/chunks/chunk.rb b/lib/chunks/chunk.rb
index 18de7d0c..46382c76 100644
--- a/lib/chunks/chunk.rb
+++ b/lib/chunks/chunk.rb
@@ -74,6 +74,14 @@ module Chunk
@content.delete_chunk(self)
end
+ def html_escape(string)
+ string.gsub( /&/, "&" ).
+ gsub( /, "<" ).
+ gsub( />/, ">" ).
+ gsub( /'/, "'" ).
+ gsub( /"/, """ )
+ end
+
end
end
diff --git a/lib/chunks/nowiki.rb b/lib/chunks/nowiki.rb
index ef99ec0b..8bad35e6 100644
--- a/lib/chunks/nowiki.rb
+++ b/lib/chunks/nowiki.rb
@@ -13,6 +13,10 @@ require 'chunks/chunk'
#
# Author: Mark Reid
# Created: 8th June 2004
+
+require 'sanitize'
+include Sanitize
+
class NoWiki < Chunk::Abstract
NOWIKI_PATTERN = Regexp.new('(.*?)', Regexp::MULTILINE)
@@ -22,7 +26,7 @@ class NoWiki < Chunk::Abstract
def initialize(match_data, content)
super
- @plain_text = @unmask_text = match_data[1]
+ @plain_text = @unmask_text = sanitize_html(match_data[1])
end
end
diff --git a/lib/sanitize.rb b/lib/sanitize.rb
index f4c479ec..92adf6ad 100644
--- a/lib/sanitize.rb
+++ b/lib/sanitize.rb
@@ -203,3 +203,28 @@ module Sanitize
style = clean.join(' ')
end
end
+
+# Some useful additions to the String class
+
+class String
+
+# Check whether a string is valid utf-8
+#
+# :call-seq:
+# string.is_utf8? -> boolean
+#
+# returns true if the sequence of bytes in string is valid utf-8
+ def is_utf8?
+ self =~ /^(
+ [\x09\x0A\x0D\x20-\x7E] # ASCII
+ | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
+ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
+ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
+ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
+ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
+ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
+ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
+ )*$/x;
+ end
+
+end
diff --git a/test/unit/chunks/category_test.rb b/test/unit/chunks/category_test.rb
index 6bc7627f..0244ee65 100755
--- a/test/unit/chunks/category_test.rb
+++ b/test/unit/chunks/category_test.rb
@@ -19,4 +19,12 @@ class CategoryTest < Test::Unit::TestCase
)
end
+ def test_multiple_categories_sanitized
+ match(Category, 'category: test, multiple,a & b ', :list => ['test', 'multiple', '<span>a & b</span> <script>alert("XSS!");</script>'], :hidden => nil
+)
+ match(Category, 'category : chunk test , multi category,a & b ',
+ :list => ['chunk test','multi category','<span>a & b</span> <script>alert("XSS!");</script>'], :hidden => nil
+ )
+ end
+
end
diff --git a/test/unit/chunks/nowiki_test.rb b/test/unit/chunks/nowiki_test.rb
index 8af5a645..fdbced54 100755
--- a/test/unit/chunks/nowiki_test.rb
+++ b/test/unit/chunks/nowiki_test.rb
@@ -12,4 +12,10 @@ class NoWikiTest < Test::Unit::TestCase
)
end
+ def test_sanitized_nowiki
+ match(NoWiki, 'This sentence contains a b . Do not touch!',
+ :plain_text => 'a b <script>alert("XSS!");</script>'
+ )
+ end
+
end