bbcoder 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +11 -9
- data/README.md +54 -10
- data/Rakefile +2 -1
- data/bbcoder.gemspec +1 -0
- data/lib/bbcoder.rb +5 -4
- data/lib/bbcoder/configuration.rb +8 -0
- data/lib/bbcoder/tag.rb +16 -1
- data/lib/bbcoder/version.rb +1 -1
- data/spec/base_spec.rb +28 -0
- data/spec/bbcoder_spec.rb +69 -2
- metadata +19 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
bbcoder (1.0.
|
4
|
+
bbcoder (1.0.1)
|
5
5
|
|
6
6
|
GEM
|
7
|
-
remote:
|
7
|
+
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
diff-lcs (1.1.3)
|
10
|
+
rake (0.9.2.2)
|
10
11
|
rr (1.0.4)
|
11
|
-
rspec (2.
|
12
|
-
rspec-core (~> 2.
|
13
|
-
rspec-expectations (~> 2.
|
14
|
-
rspec-mocks (~> 2.
|
15
|
-
rspec-core (2.
|
16
|
-
rspec-expectations (2.
|
12
|
+
rspec (2.10.0)
|
13
|
+
rspec-core (~> 2.10.0)
|
14
|
+
rspec-expectations (~> 2.10.0)
|
15
|
+
rspec-mocks (~> 2.10.0)
|
16
|
+
rspec-core (2.10.0)
|
17
|
+
rspec-expectations (2.10.0)
|
17
18
|
diff-lcs (~> 1.1.3)
|
18
|
-
rspec-mocks (2.
|
19
|
+
rspec-mocks (2.10.1)
|
19
20
|
|
20
21
|
PLATFORMS
|
21
22
|
ruby
|
22
23
|
|
23
24
|
DEPENDENCIES
|
24
25
|
bbcoder!
|
26
|
+
rake
|
25
27
|
rr
|
26
28
|
rspec
|
data/README.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
Status
|
2
|
+
--------
|
3
|
+
I consider bbcoder to be stable so you won't see many updates to it in the future. It is perfectly fine to use in prodution. The gem itself is pretty simple so it should work across
|
4
|
+
the board with newer frameworks etc. If you find any issues or think it needs a feature please submit an issue.
|
5
|
+
|
6
|
+
|
1
7
|
Features
|
2
8
|
--------
|
3
9
|
|
@@ -13,9 +19,13 @@ p, b, i, u, s, del, ins, ol, ul, li, dl, dt, dd, quote, code, spoiler, url, img,
|
|
13
19
|
Usage
|
14
20
|
--------
|
15
21
|
|
16
|
-
BBCoder.new(text).to_html
|
22
|
+
BBCoder.new(h(text)).to_html
|
17
23
|
# or
|
18
|
-
"[p]my string[/p]".bbcode_to_html
|
24
|
+
h("[p]my string[/p]").bbcode_to_html
|
25
|
+
# h() is a Rails helper function, you may use CGI.escapeHTML instead
|
26
|
+
|
27
|
+
See configuration section below on adding new parseable tags
|
28
|
+
|
19
29
|
|
20
30
|
Install
|
21
31
|
-------
|
@@ -23,6 +33,36 @@ Install
|
|
23
33
|
gem install bbcoder
|
24
34
|
|
25
35
|
|
36
|
+
Autolinking, Smileys, XSS prevention, Newlines
|
37
|
+
--------------------------------------
|
38
|
+
|
39
|
+
bbcoder is not meant to handle smileys, autolinking or xss attacks. There are other libraries to help do this for us. I also do not consider these elements part of bbcode itself (even though there is no standard) so bbcoder will not provide support for them except in this README to give examples on how to combine them together.
|
40
|
+
|
41
|
+
|
42
|
+
#### Autolinking
|
43
|
+
Rails 2.x has a helper auto_link by default that can do this for you. For Rails 3.x you can install the rails_autolink gem.
|
44
|
+
|
45
|
+
|
46
|
+
#### Smileys
|
47
|
+
At the moment I use a jquery library to display smileys after the page has loaded. The library I use https://github.com/JangoSteve/jQuery-CSSEmoticons however it would be nice to see a gem that can parse smileys out of text into appropriate html elements with specific tags. CSS3 font-face anyone?
|
48
|
+
|
49
|
+
|
50
|
+
#### XSS
|
51
|
+
Please make sure you escaped or sanitized all HTML in the string before passing it to bbcoder!
|
52
|
+
|
53
|
+
bbcoder will now do a whitelist check against img tags and url tags by default and only allow http/https links. You can override this by putting in your own configuration if you wish. If you find any other flaws or holes please report so we can fix. bbcoder will not sanitize the rest of your input, it will only attempt to whitelist the actual html elements it will generate.
|
54
|
+
|
55
|
+
|
56
|
+
#### Newlines
|
57
|
+
When typing into a textarea a user will use newlines to indicate space between lines. This is not translated properly into br tags. I do not consider this a function for bbcoder either atm, however I do use it in combination with XSS/Sanitize above:
|
58
|
+
|
59
|
+
|
60
|
+
##### XSS + Newlines Helper
|
61
|
+
def bbcode(text)
|
62
|
+
Sanitize.clean(text.to_s).bbcode_to_html.gsub(/\n|\r\n/, "<br />").html_safe
|
63
|
+
end
|
64
|
+
|
65
|
+
|
26
66
|
Configuration Examples
|
27
67
|
-----------------------
|
28
68
|
|
@@ -41,7 +81,15 @@ Configuration Examples
|
|
41
81
|
tag :ol
|
42
82
|
tag :li, :parents => [:ol, :ul]
|
43
83
|
|
44
|
-
tag :
|
84
|
+
tag :url, :match_link => /^https?:\/\// do
|
85
|
+
if meta.nil? || meta.empty?
|
86
|
+
%(<a href="#{content}">#{content}</a>)
|
87
|
+
else
|
88
|
+
%(<a href="#{meta}">#{content}</a>)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
tag :img, :match => /^https?:\/\/.*(png|bmp|jpe?g|gif)$/, :singular => true do
|
45
93
|
%(<a href="#{singular? ? meta : content}"><img src="#{singular? ? meta : content}" /></a>)
|
46
94
|
end
|
47
95
|
|
@@ -53,13 +101,7 @@ Configuration Examples
|
|
53
101
|
EOS
|
54
102
|
end
|
55
103
|
|
56
|
-
|
57
|
-
if meta.nil? || meta.empty?
|
58
|
-
%(<a href="#{content}">#{content}</a>)
|
59
|
-
else
|
60
|
-
%(<a href="#{meta}">#{content}</a>)
|
61
|
-
end
|
62
|
-
end
|
104
|
+
remove :spoiler # Removes [spoiler]
|
63
105
|
end
|
64
106
|
|
65
107
|
|
@@ -69,6 +111,7 @@ Options for #tag
|
|
69
111
|
* :match (regex) -> convert this tag and its content to html only if the content and meta matches the regex (see img tag above for example)
|
70
112
|
* :match_meta (regex) -> same as :match except only for meta
|
71
113
|
* :match_content (regex) -> same as :match except only for content
|
114
|
+
* :match_link (regex) -> special :match case, will match meta if it exists otherwise tries to match content (see url tag for usage)
|
72
115
|
* :parents ([symbol]) -> ignore this tag if there is no open tag that matches its parents
|
73
116
|
* :singular (true|false) -> use this if the tag does not require an ending tag
|
74
117
|
|
@@ -79,6 +122,7 @@ When you pass a block to #tag it is expecting you to return a string. You have
|
|
79
122
|
* content -> Everything between the two tags (with [b]strong arm[/b] content returns 'strong arm')
|
80
123
|
* singular? -> Tells you if this tag is being parsed in singular form or if it had an ending tag (affects if content has any data)
|
81
124
|
|
125
|
+
You can remove all configured tags by calling `BBCoder.configuration.clear`.
|
82
126
|
|
83
127
|
Author
|
84
128
|
------
|
data/Rakefile
CHANGED
@@ -4,13 +4,14 @@ Bundler.setup
|
|
4
4
|
require "rspec"
|
5
5
|
require "rspec/core/rake_task"
|
6
6
|
|
7
|
-
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
8
|
|
9
9
|
gemspec = eval(File.read(File.join(Dir.pwd, "bbcoder.gemspec")))
|
10
10
|
|
11
11
|
task :build => "#{gemspec.full_name}.gem"
|
12
12
|
|
13
13
|
task :test => :spec
|
14
|
+
task :default => :spec
|
14
15
|
|
15
16
|
file "#{gemspec.full_name}.gem" => gemspec.files + ["bbcoder.gemspec"] do
|
16
17
|
system "gem build bbcoder.gemspec"
|
data/bbcoder.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
s.add_development_dependency 'rake'
|
21
22
|
s.add_development_dependency 'rspec'
|
22
23
|
s.add_development_dependency 'rr'
|
23
24
|
end
|
data/lib/bbcoder.rb
CHANGED
@@ -21,9 +21,10 @@ BBCoder.configure do
|
|
21
21
|
tag :dd, :parents => [:dl]
|
22
22
|
|
23
23
|
tag :quote do
|
24
|
+
quoted = meta.empty? ? '' : "\n <legend>#{meta} says</legend>"
|
25
|
+
|
24
26
|
<<-EOS
|
25
|
-
<fieldset
|
26
|
-
<legend>#{meta} says</legend>
|
27
|
+
<fieldset>#{quoted}
|
27
28
|
<blockquote>
|
28
29
|
#{content}
|
29
30
|
</blockquote>
|
@@ -48,7 +49,7 @@ BBCoder.configure do
|
|
48
49
|
EOS
|
49
50
|
end
|
50
51
|
|
51
|
-
tag :url do
|
52
|
+
tag :url, :match_link => /^https?:\/\// do
|
52
53
|
if meta.nil? || meta.empty?
|
53
54
|
%(<a href="#{content}">#{content}</a>)
|
54
55
|
else
|
@@ -56,7 +57,7 @@ BBCoder.configure do
|
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
|
-
tag :img, :match =>
|
60
|
+
tag :img, :match => /^https?:\/\/.*(png|bmp|jpe?g|gif)$/, :singular => true do
|
60
61
|
%(<a href="#{singular? ? meta : content}"><img src="#{singular? ? meta : content}" /></a>)
|
61
62
|
end
|
62
63
|
|
data/lib/bbcoder/tag.rb
CHANGED
@@ -8,7 +8,9 @@ class BBCoder
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def to_html(meta, content, singularity = false)
|
11
|
-
|
11
|
+
unless content_valid?(content, singularity) && meta_valid?(meta, singularity) && link_valid?(meta, content)
|
12
|
+
return self.class.reform(name, meta, content, singularity, true)
|
13
|
+
end
|
12
14
|
|
13
15
|
if options[:block].nil?
|
14
16
|
"<#{options[:as]}>#{content}</#{options[:as]}>"
|
@@ -22,6 +24,19 @@ class BBCoder
|
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
27
|
+
def link_valid?(meta, content)
|
28
|
+
# only run if we have a :match_link
|
29
|
+
return true if options[:match_link].nil?
|
30
|
+
|
31
|
+
if meta.nil? || meta.empty?
|
32
|
+
return false if content.match(options[:match_link]).nil?
|
33
|
+
else
|
34
|
+
return false if meta.match(options[:match_link]).nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
return true
|
38
|
+
end
|
39
|
+
|
25
40
|
def meta_valid?(meta, singularity)
|
26
41
|
return true if meta.nil?
|
27
42
|
|
data/lib/bbcoder/version.rb
CHANGED
data/spec/base_spec.rb
CHANGED
@@ -5,9 +5,22 @@ describe BBCoder do
|
|
5
5
|
subject { BBCoder.new("[p]Text and now [b]bolded.[/b][/p]") }
|
6
6
|
|
7
7
|
context "#configuration" do
|
8
|
+
before do
|
9
|
+
@tags = BBCoder::Configuration.class_variable_get(:@@tags).clone
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
BBCoder::Configuration.class_variable_set(:@@tags, @tags)
|
14
|
+
end
|
15
|
+
|
8
16
|
it "should return the same object for multiple calls" do
|
9
17
|
BBCoder.configuration.should == BBCoder.configuration
|
10
18
|
end
|
19
|
+
|
20
|
+
it "should allow to clear the configuration" do
|
21
|
+
BBCoder.configuration.clear
|
22
|
+
BBCoder.configuration[:spoiler].should be_nil
|
23
|
+
end
|
11
24
|
end
|
12
25
|
|
13
26
|
context "#buffer" do
|
@@ -17,6 +30,14 @@ describe BBCoder do
|
|
17
30
|
end
|
18
31
|
|
19
32
|
context "#configure" do
|
33
|
+
before do
|
34
|
+
@tags = BBCoder::Configuration.class_variable_get(:@@tags).clone
|
35
|
+
end
|
36
|
+
|
37
|
+
after do
|
38
|
+
BBCoder::Configuration.class_variable_set(:@@tags, @tags)
|
39
|
+
end
|
40
|
+
|
20
41
|
it "should fail without a block" do
|
21
42
|
lambda { BBCoder.configure }.should raise_error
|
22
43
|
end
|
@@ -26,6 +47,13 @@ describe BBCoder do
|
|
26
47
|
mock(BBCoder).configuration.stub!.instance_eval(&block)
|
27
48
|
BBCoder.configure(&block)
|
28
49
|
end
|
50
|
+
|
51
|
+
it "should be able to remove a tag" do
|
52
|
+
BBCoder.configure do
|
53
|
+
remove :spoiler
|
54
|
+
end
|
55
|
+
BBCoder.configuration[:spoiler].should be_nil
|
56
|
+
end
|
29
57
|
end
|
30
58
|
|
31
59
|
context "#initialize" do
|
data/spec/bbcoder_spec.rb
CHANGED
@@ -2,6 +2,33 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe BBCoder do
|
4
4
|
|
5
|
+
context "quotes" do
|
6
|
+
it "displays the quoted party if provided" do
|
7
|
+
string = "[quote=weedman]Said some thing about some stuff[/quote]"
|
8
|
+
|
9
|
+
string.bbcode_to_html.should == <<-EOS
|
10
|
+
<fieldset>
|
11
|
+
<legend>weedman says</legend>
|
12
|
+
<blockquote>
|
13
|
+
Said some thing about some stuff
|
14
|
+
</blockquote>
|
15
|
+
</fieldset>
|
16
|
+
EOS
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has no legend if no quoted party provided" do
|
20
|
+
string = "[quote]Said some thing about some stuff[/quote]"
|
21
|
+
|
22
|
+
string.bbcode_to_html.should == <<-EOS
|
23
|
+
<fieldset>
|
24
|
+
<blockquote>
|
25
|
+
Said some thing about some stuff
|
26
|
+
</blockquote>
|
27
|
+
</fieldset>
|
28
|
+
EOS
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
5
32
|
context "with dirty input" do
|
6
33
|
it "should parse content with \" in it" do
|
7
34
|
'[p]Text phrase: "going away"[/p]'.bbcode_to_html.should == '<p>Text phrase: "going away"</p>'
|
@@ -20,7 +47,7 @@ describe BBCoder do
|
|
20
47
|
|
21
48
|
result = <<-EOS
|
22
49
|
<fieldset>
|
23
|
-
<legend>weedman says</legend>
|
50
|
+
<legend>weedman says</legend>
|
24
51
|
<blockquote>
|
25
52
|
YES I STICKY IT ALL oF YOU WHO DON\'T LIKE it SEND YOUR HATE HERE\n\nhttp://www.gamesyn.com/plugin.php?plugin=PrivateMessages&file=message_send.php&id=20&tid=1583\n\n:} have a good day
|
26
53
|
</blockquote>
|
@@ -67,7 +94,6 @@ EOS
|
|
67
94
|
output = "[p]Text and now [b]bold then [i]italics[/i][/b][/p] and then a [quote]Quote[/quote]".bbcode_to_html
|
68
95
|
output.should == <<-EOS
|
69
96
|
<p>Text and now <strong>bold then <em>italics</em></strong></p> and then a <fieldset>
|
70
|
-
<legend> says</legend>
|
71
97
|
<blockquote>
|
72
98
|
Quote
|
73
99
|
</blockquote>
|
@@ -151,5 +177,46 @@ EOS
|
|
151
177
|
"[img=image.exe]".bbcode_to_html.should == "[img=image.exe]"
|
152
178
|
end
|
153
179
|
end
|
180
|
+
|
181
|
+
context "with xss attacks" do
|
182
|
+
it "should reject anything other than http/https for url tags" do
|
183
|
+
"[url=javascript:alert('You got hacked!')]hacked[/url]".bbcode_to_html.should == "[url=javascript:alert('You got hacked!')]hacked[/url]"
|
184
|
+
"[url]javascript:alert('You got hacked!')[/url]".bbcode_to_html.should == "[url]javascript:alert('You got hacked!')[/url]"
|
185
|
+
|
186
|
+
'[url=javascript:window.alert("You got hacked!")]click[/url]'.bbcode_to_html.should == '[url=javascript:window.alert("You got hacked!")]click[/url]'
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should reject anything other than http/https for img tags" do
|
190
|
+
"[img=javascript:alert('XSS');jpg]".bbcode_to_html.should == "[img=javascript:alert('XSS');jpg]"
|
191
|
+
"[img]javascript:alert('XSS');png[/img]".bbcode_to_html.should == "[img]javascript:alert('XSS');png[/img]"
|
192
|
+
'[img]javascript:window.alert("You got hacked!")//.jpg[/img]'.bbcode_to_html.should == '[img]javascript:window.alert("You got hacked!")//.jpg[/img]'
|
193
|
+
|
194
|
+
attack = "[img]
|
195
|
+
j
|
196
|
+
a
|
197
|
+
v
|
198
|
+
a
|
199
|
+
s
|
200
|
+
c
|
201
|
+
r
|
202
|
+
i
|
203
|
+
p
|
204
|
+
t
|
205
|
+
:
|
206
|
+
a
|
207
|
+
l
|
208
|
+
e
|
209
|
+
r
|
210
|
+
t
|
211
|
+
(
|
212
|
+
'
|
213
|
+
X
|
214
|
+
S
|
215
|
+
S
|
216
|
+
'
|
217
|
+
);jpg[/img]"
|
218
|
+
attack.bbcode_to_html.should == attack
|
219
|
+
end
|
220
|
+
end
|
154
221
|
end
|
155
222
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bbcoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-11-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: rspec
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -92,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
108
|
version: '0'
|
93
109
|
requirements: []
|
94
110
|
rubyforge_project: bbcoder
|
95
|
-
rubygems_version: 1.8.
|
111
|
+
rubygems_version: 1.8.23
|
96
112
|
signing_key:
|
97
113
|
specification_version: 3
|
98
114
|
summary: BBCode parser
|