erb_safe_ext 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b0b6a5f0daa578acddae3d8949d930a82785e59
4
+ data.tar.gz: 1c853f1d551d56c70c6fc61461e63f85a6dd99d3
5
+ SHA512:
6
+ metadata.gz: fc649276d7b03e42808a468a92209cb40aa802036f7efddbe19f03c3dc6524c72c644b73ef5c5b901c181b030aaa8ea26598fe01f47a6b2d092f43ca566b4aad
7
+ data.tar.gz: 1624272061c380efd61ed94b731e210308ce35f84bf6e4bca722c9ec7a72e8f07c18c0286cb590fd35ca43b2d3a7b7c2e172b0a487e4e01dd4a1fe6a5be9f36d
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # erb_safe_ext
2
+
3
+ a gem make ERB html safe default.Protect from XSS attack.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ $ gem install erb_safe_ext
9
+ ```
10
+
11
+ ## Introduction
12
+
13
+ ``` erb
14
+ <%= "<script>alert('safety:)');</script>" %>
15
+ ## => &lt;script&gt;alert(&#x27;safety:)&#x27;);&lt;&#x2F;script&gt;
16
+ ```
17
+
18
+ it will default wrap the dangerous code with `Rack::Utils.escape_html(code)`
19
+
20
+ works fine with ruby2.1.
21
+
22
+ I didn't test this code with other version ruby, you may test yourself.
23
+
24
+ the `<%==` is the backup of ERB's original `<%=` function.
25
+
26
+ ``` erb
27
+ <%== "<script>alert('danger!');</script>" %>
28
+ ## => <script>alert('danger!');</script>
29
+ ```
30
+
31
+
32
+ Test code
33
+
34
+ ``` ruby
35
+ require 'erb_safe_ext'
36
+ template = ERB.new <<-EOF
37
+ <%= "<script>alert('safety:)');</script>" %>
38
+ <%#= 'here' -%>
39
+ <%== "<script>alert('danger!');</script>" %>
40
+ ----finish----
41
+ EOF
42
+ puts template.result
43
+ ```
44
+
45
+
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sinarey_cache/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "erb_safe_ext"
8
+ spec.version = '1.0'
9
+ spec.authors = ["Jeffrey"]
10
+ spec.email = ["jeffrey6052@163.com"]
11
+ spec.description = "make ERB default html safe.protect from XSS attack."
12
+ spec.summary = "wrap the dangerous code with Rack::Utils.escape_html()"
13
+ spec.homepage = "https://github.com/maymay25/erb_safe_ext"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = ['lib/erb_safe_ext.rb',
17
+ 'test/erb_safe_test.rb',
18
+ 'erb_safe_ext.gemspec',
19
+ 'README.md']
20
+ end
@@ -0,0 +1,190 @@
1
+ require 'erb'
2
+ require 'rack'
3
+
4
+ class ERB
5
+ class Compiler
6
+ def compile(s)
7
+ enc = s.encoding
8
+ raise ArgumentError, "#{enc} is not ASCII compatible" if enc.dummy?
9
+ s = s.dup.force_encoding("ASCII-8BIT") # don't use constant Enoding::ASCII_8BIT for miniruby
10
+ enc = detect_magic_comment(s) || enc
11
+ out = Buffer.new(self, enc)
12
+ content = ''
13
+ scanner = make_scanner(s)
14
+ scanner.scan do |token|
15
+ next if token.nil?
16
+ next if token == ''
17
+ if scanner.stag.nil?
18
+ case token
19
+ when PercentLine
20
+ add_put_cmd(out, content) if content.size > 0
21
+ content = ''
22
+ out.push(token.to_s)
23
+ out.cr
24
+ when :cr
25
+ out.cr
26
+ when '<%', '<%==', '<%=', '<%#'
27
+ scanner.stag = token
28
+ add_put_cmd(out, content) if content.size > 0
29
+ content = ''
30
+ when "\n"
31
+ content << "\n"
32
+ add_put_cmd(out, content)
33
+ content = ''
34
+ when '<%%'
35
+ content << '<%'
36
+ else
37
+ content << token
38
+ end
39
+ else
40
+ case token
41
+ when '%>'
42
+ case scanner.stag
43
+ when '<%'
44
+ if content[-1] == ?\n
45
+ content.chop!
46
+ out.push(content)
47
+ out.cr
48
+ else
49
+ out.push(content)
50
+ end
51
+ when '<%=='
52
+ add_insert_cmd(out, content)
53
+ when '<%='
54
+ add_insert_escapehtml_cmd(out, content)
55
+ when '<%#'
56
+ # out.push("# #{content_dump(content)}")
57
+ end
58
+ scanner.stag = nil
59
+ content = ''
60
+ when '%%>'
61
+ content << '%>'
62
+ else
63
+ content << token
64
+ end
65
+ end
66
+ end
67
+ add_put_cmd(out, content) if content.size > 0
68
+ out.close
69
+ return out.script, enc
70
+ end
71
+ def add_insert_escapehtml_cmd(out, content)
72
+ out.push("#{@insert_cmd}(('#{Rack::Utils.escape_html(eval(content))}').to_s)")
73
+ end
74
+ class TrimScanner < Scanner
75
+ def scan_line(line)
76
+ line.scan(/(.*?)(<%%|%%>|<%==|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
77
+ tokens.each do |token|
78
+ next if token.empty?
79
+ yield(token)
80
+ end
81
+ end
82
+ end
83
+ def trim_line1(line)
84
+ line.scan(/(.*?)(<%%|%%>|<%==|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
85
+ tokens.each do |token|
86
+ next if token.empty?
87
+ if token == "%>\n"
88
+ yield('%>')
89
+ yield(:cr)
90
+ else
91
+ yield(token)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ def trim_line2(line)
97
+ head = nil
98
+ line.scan(/(.*?)(<%%|%%>|<%==|<%=|<%#|<%|%>\n|%>|\n|\z)/m) do |tokens|
99
+ tokens.each do |token|
100
+ next if token.empty?
101
+ head = token unless head
102
+ if token == "%>\n"
103
+ yield('%>')
104
+ if is_erb_stag?(head)
105
+ yield(:cr)
106
+ else
107
+ yield("\n")
108
+ end
109
+ head = nil
110
+ else
111
+ yield(token)
112
+ head = nil if token == "\n"
113
+ end
114
+ end
115
+ end
116
+ end
117
+ def explicit_trim_line(line)
118
+ line.scan(/(.*?)(^[ \t]*<%\-|<%\-|<%%|%%>|<%==|<%=|<%#|<%|-%>\n|-%>|%>|\z)/m) do |tokens|
119
+ tokens.each do |token|
120
+ next if token.empty?
121
+ if @stag.nil? && /[ \t]*<%-/ =~ token
122
+ yield('<%')
123
+ elsif @stag && token == "-%>\n"
124
+ yield('%>')
125
+ yield(:cr)
126
+ elsif @stag && token == '-%>'
127
+ yield('%>')
128
+ else
129
+ yield(token)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ ERB_STAG << '<%=='
135
+ def is_erb_stag?(s)
136
+ ERB_STAG.member?(s)
137
+ end
138
+ end
139
+ Scanner.default_scanner = TrimScanner
140
+ class SimpleScanner < Scanner # :nodoc:
141
+ def scan
142
+ @src.scan(/(.*?)(<%%|%%>|<%==|<%=|<%#|<%|%>|\n|\z)/m) do |tokens|
143
+ tokens.each do |token|
144
+ next if token.empty?
145
+ yield(token)
146
+ end
147
+ end
148
+ end
149
+ end
150
+ Scanner.regist_scanner(SimpleScanner, nil, false)
151
+ begin
152
+ require 'strscan'
153
+ class SimpleScanner2 < Scanner # :nodoc:
154
+ def scan
155
+ stag_reg = /(.*?)(<%%|<%==|<%=|<%#|<%|\z)/m
156
+ etag_reg = /(.*?)(%%>|%>|\z)/m
157
+ scanner = StringScanner.new(@src)
158
+ while ! scanner.eos?
159
+ scanner.scan(@stag ? etag_reg : stag_reg)
160
+ yield(scanner[1])
161
+ yield(scanner[2])
162
+ end
163
+ end
164
+ end
165
+ Scanner.regist_scanner(SimpleScanner2, nil, false)
166
+ class ExplicitScanner < Scanner # :nodoc:
167
+ def scan
168
+ stag_reg = /(.*?)(^[ \t]*<%-|<%%|<%==|<%=|<%#|<%-|<%|\z)/m
169
+ etag_reg = /(.*?)(%%>|-%>|%>|\z)/m
170
+ scanner = StringScanner.new(@src)
171
+ while ! scanner.eos?
172
+ scanner.scan(@stag ? etag_reg : stag_reg)
173
+ yield(scanner[1])
174
+ elem = scanner[2]
175
+ if /[ \t]*<%-/ =~ elem
176
+ yield('<%')
177
+ elsif elem == '-%>'
178
+ yield('%>')
179
+ yield(:cr) if scanner.scan(/(\n|\z)/)
180
+ else
181
+ yield(elem)
182
+ end
183
+ end
184
+ end
185
+ end
186
+ Scanner.regist_scanner(ExplicitScanner, '-', false)
187
+ rescue LoadError
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,14 @@
1
+
2
+ $:.unshift File.expand_path("../lib", __dir__)
3
+
4
+ require 'erb_safe_ext'
5
+
6
+ template = ERB.new <<-EOF
7
+ <%= "hello, #{'world'}." %>
8
+ <%= "<script>alert('safety:)');</script>" %>
9
+ <%== "<script>alert('danger!');</script>" %>
10
+ this is the end.
11
+ EOF
12
+ puts template.result
13
+
14
+
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: erb_safe_ext
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Jeffrey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-27 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: make ERB default html safe.protect from XSS attack.
14
+ email:
15
+ - jeffrey6052@163.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/erb_safe_ext.rb
21
+ - test/erb_safe_test.rb
22
+ - erb_safe_ext.gemspec
23
+ - README.md
24
+ homepage: https://github.com/maymay25/erb_safe_ext
25
+ licenses:
26
+ - MIT
27
+ metadata: {}
28
+ post_install_message:
29
+ rdoc_options: []
30
+ require_paths:
31
+ - lib
32
+ required_ruby_version: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ required_rubygems_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 2.0.14
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: wrap the dangerous code with Rack::Utils.escape_html()
48
+ test_files: []