escape_utils 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,5 @@
1
1
  Makefile
2
2
  *.o
3
- *.bundle
3
+ *.bundle
4
+ pkg/*
5
+ doc/*
@@ -1,4 +1,7 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1 (June 8th, 2010)
4
+ * added javascript escaping
5
+
3
6
  ## 0.1.0 (June 8th, 2010)
4
7
  * initial release
@@ -2,7 +2,7 @@
2
2
 
3
3
  Being as though we're all html escaping everything these days, why not make it faster?
4
4
 
5
- At the moment escape_utils supports escaping and unescaping of HTML, but I wanna add URL encoding soon
5
+ At the moment escape_utils supports escaping and unescaping of HTML, and Javascript but I wanna add URL encoding soon
6
6
 
7
7
  It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml
8
8
 
@@ -23,6 +23,11 @@ It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml
23
23
  escaped_html = EscapeUtils.escape_html(html)
24
24
  html = EscapeUtils.unescape_html(escaped_html)
25
25
 
26
+ === Escaping Javascript
27
+
28
+ javascript = `curl -s http://code.jquery.com/jquery-1.4.2.js`
29
+ escaped_javascript = EscapeUtils.escape_javascript(javascript)
30
+
26
31
  === Monkey Patches
27
32
 
28
33
  require 'escape_utils/rack' # to patch Rack::Utils
@@ -33,11 +38,11 @@ It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml
33
38
  == Benchmarks
34
39
 
35
40
  In my testing, escaping is around 10-20x faster than the pure ruby implementations in wide use today.
36
- While unescaping is around 24x faster than CGI.unescapeHTML - also pure ruby.
41
+ While unescaping is around 20-40x faster than CGI.unescapeHTML - also pure ruby.
37
42
 
38
43
  This output is from my laptop using the benchmark scripts in the benchmarks folder.
39
44
 
40
- === Escaping
45
+ === HTML Escaping
41
46
 
42
47
  Rack::Utils.escape_html
43
48
  0.560000 0.040000 0.600000 ( 0.589475)
@@ -50,9 +55,16 @@ This output is from my laptop using the benchmark scripts in the benchmarks fold
50
55
  EscapeUtils.escape_html
51
56
  0.050000 0.010000 0.060000 ( 0.054799)
52
57
 
53
- === Unescaping
58
+ === HTML Unescaping
54
59
 
55
60
  CGI.unescapeHTML
56
61
  1.140000 0.010000 1.150000 ( 1.148470)
57
62
  EscapeUtils.unescape_html
58
- 0.040000 0.000000 0.040000 ( 0.046166)
63
+ 0.040000 0.000000 0.040000 ( 0.046166)
64
+
65
+ === Javascript Escaping
66
+
67
+ ActionView::Helpers::JavaScriptHelper#escape_javascript
68
+ 2.000000 0.020000 2.020000 ( 2.023047)
69
+ EscapeUtils.escape_javascript
70
+ 0.110000 0.010000 0.120000 ( 0.121761)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
File without changes
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/..')
3
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'rubygems'
6
+ require 'benchmark'
7
+
8
+ require 'action_view'
9
+ require 'escape_utils'
10
+
11
+ class ActionPackBench
12
+ extend ActionView::Helpers::JavaScriptHelper
13
+ end
14
+
15
+ times = 100
16
+ url = "http://code.jquery.com/jquery-1.4.2.js"
17
+ javascript = `curl -s #{url}`
18
+ puts "Escaping #{javascript.bytesize} bytes of javascript from #{url}"
19
+
20
+ puts ActionPackBench.escape_javascript(javascript).eql?(EscapeUtils.escape_javascript(javascript))
21
+
22
+ Benchmark.bmbm do |x|
23
+ x.report do
24
+ puts "ActionView::Helpers::JavaScriptHelper#escape_javascript"
25
+ times.times do
26
+ ActionPackBench.escape_javascript(javascript)
27
+ end
28
+ end
29
+
30
+ x.report do
31
+ puts "EscapeUtils.escape_javascript"
32
+ times.times do
33
+ EscapeUtils.escape_javascript(javascript)
34
+ end
35
+ end
36
+ end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{escape_utils}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Brian Lopez"]
@@ -22,8 +22,9 @@ Gem::Specification.new do |s|
22
22
  "README.rdoc",
23
23
  "Rakefile",
24
24
  "VERSION",
25
- "benchmark/escape.rb",
26
- "benchmark/unescape.rb",
25
+ "benchmark/html_escape.rb",
26
+ "benchmark/html_unescape.rb",
27
+ "benchmark/javascript_escape.rb",
27
28
  "escape_utils.gemspec",
28
29
  "ext/escape_utils.c",
29
30
  "ext/extconf.rb",
@@ -34,6 +35,7 @@ Gem::Specification.new do |s|
34
35
  "lib/escape_utils/rack.rb",
35
36
  "spec/html/escape_spec.rb",
36
37
  "spec/html/unescape_spec.rb",
38
+ "spec/javascript/escape_spec.rb",
37
39
  "spec/rcov.opts",
38
40
  "spec/spec.opts",
39
41
  "spec/spec_helper.rb"
@@ -46,6 +48,7 @@ Gem::Specification.new do |s|
46
48
  s.test_files = [
47
49
  "spec/html/escape_spec.rb",
48
50
  "spec/html/unescape_spec.rb",
51
+ "spec/javascript/escape_spec.rb",
49
52
  "spec/spec_helper.rb"
50
53
  ]
51
54
 
@@ -72,7 +72,39 @@ static size_t unescape_html(unsigned char *out, const unsigned char *in, size_t
72
72
  return total + (i-offset);
73
73
  }
74
74
 
75
+ static size_t escape_javascript(unsigned char *out, const unsigned char *in, size_t in_len) {
76
+ size_t i = 0, offset = 0, total = 0;
77
+
78
+ for(;i<in_len;i++) {
79
+ switch(in[i]) {
80
+ case '\\': APPEND_BUFFER("\\\\", 2, 1);
81
+ case '<':
82
+ if (i+1 <= in_len && in[i+1] == '/') {
83
+ APPEND_BUFFER("<\\/", 3, 2);
84
+ }
85
+ break;
86
+ case '\r':
87
+ if (i+1 <= in_len && in[i+1] == '\n') {
88
+ APPEND_BUFFER("\\n", 2, 1);
89
+ } else {
90
+ APPEND_BUFFER("\\n", 2, 1);
91
+ }
92
+ break;
93
+ case '\n': APPEND_BUFFER("\\n", 2, 1);
94
+ case '\"': APPEND_BUFFER("\\\"", 2, 1);
95
+ case '\'': APPEND_BUFFER("\\'", 2, 1);
96
+ }
97
+ }
98
+
99
+ // append the rest of the buffer
100
+ memcpy(&out[total], &in[offset], i-offset);
101
+
102
+ return total + (i-offset);
103
+ }
104
+
75
105
  static VALUE rb_escape_html(VALUE self, VALUE str) {
106
+ Check_Type(str, T_STRING);
107
+
76
108
  VALUE rb_output_buf;
77
109
  unsigned char *inBuf = (unsigned char*)RSTRING_PTR(str);
78
110
  size_t len = RSTRING_LEN(str), new_len = 0;
@@ -94,6 +126,8 @@ static VALUE rb_escape_html(VALUE self, VALUE str) {
94
126
  }
95
127
 
96
128
  static VALUE rb_unescape_html(VALUE self, VALUE str) {
129
+ Check_Type(str, T_STRING);
130
+
97
131
  VALUE rb_output_buf;
98
132
  unsigned char *inBuf = (unsigned char*)RSTRING_PTR(str);
99
133
  size_t len = RSTRING_LEN(str), new_len = 0;
@@ -114,6 +148,33 @@ static VALUE rb_unescape_html(VALUE self, VALUE str) {
114
148
  return rb_output_buf;
115
149
  }
116
150
 
151
+ static VALUE rb_escape_javascript(VALUE self, VALUE str) {
152
+ if (str == Qnil) {
153
+ return rb_str_new2("");
154
+ }
155
+
156
+ Check_Type(str, T_STRING);
157
+
158
+ VALUE rb_output_buf;
159
+ unsigned char *inBuf = (unsigned char*)RSTRING_PTR(str);
160
+ size_t len = RSTRING_LEN(str), new_len = 0;
161
+
162
+ // this is the max size the string could be
163
+ // TODO: we should try to be more intelligent about this
164
+ unsigned char *outBuf = (unsigned char *)malloc(sizeof(unsigned char *)*(len*2));
165
+
166
+ // perform our escape, returning the new string's length
167
+ new_len = escape_javascript(outBuf, inBuf, len);
168
+
169
+ // create our new ruby string
170
+ rb_output_buf = rb_str_new((char *)outBuf, new_len);
171
+
172
+ // free the temporary C string
173
+ free(outBuf);
174
+
175
+ return rb_output_buf;
176
+ }
177
+
117
178
  /* Ruby Extension initializer */
118
179
  void Init_escape_utils_ext() {
119
180
  VALUE mEscape = rb_define_module("EscapeUtils");
@@ -121,4 +182,6 @@ void Init_escape_utils_ext() {
121
182
  rb_define_module_function(mEscape, "escape_html", rb_escape_html, 1);
122
183
  rb_define_method(mEscape, "unescape_html", rb_unescape_html, 1);
123
184
  rb_define_module_function(mEscape, "unescape_html", rb_unescape_html, 1);
185
+ rb_define_method(mEscape, "escape_javascript", rb_escape_javascript, 1);
186
+ rb_define_module_function(mEscape, "escape_javascript", rb_escape_javascript, 1);
124
187
  }
@@ -4,5 +4,5 @@ require 'escape_utils_ext'
4
4
 
5
5
  EscapeUtils.send(:extend, EscapeUtils)
6
6
  module EscapeUtils
7
- VERSION = "0.0.1"
7
+ VERSION = "0.1.1"
8
8
  end
@@ -1,26 +1,24 @@
1
1
  # encoding: UTF-8
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
3
3
 
4
- describe EscapeUtils do
4
+ describe EscapeUtils, "escape_html" do
5
5
  it "should respond to escape_html" do
6
6
  EscapeUtils.should respond_to(:escape_html)
7
7
  end
8
8
 
9
- context "escape_html" do
10
- it "should escape a basic html tag" do
11
- EscapeUtils.escape_html("<some_tag/>").should eql("&lt;some_tag/&gt;")
12
- end
9
+ it "should escape a basic html tag" do
10
+ EscapeUtils.escape_html("<some_tag/>").should eql("&lt;some_tag/&gt;")
11
+ end
13
12
 
14
- it "should escape double-quotes" do
15
- EscapeUtils.escape_html("<some_tag some_attr=\"some value\"/>").should eql("&lt;some_tag some_attr=&quot;some value&quot;/&gt;")
16
- end
13
+ it "should escape double-quotes" do
14
+ EscapeUtils.escape_html("<some_tag some_attr=\"some value\"/>").should eql("&lt;some_tag some_attr=&quot;some value&quot;/&gt;")
15
+ end
17
16
 
18
- it "should escape single-quotes" do
19
- EscapeUtils.escape_html("<some_tag some_attr='some value'/>").should eql("&lt;some_tag some_attr=&#39;some value&#39;/&gt;")
20
- end
17
+ it "should escape single-quotes" do
18
+ EscapeUtils.escape_html("<some_tag some_attr='some value'/>").should eql("&lt;some_tag some_attr=&#39;some value&#39;/&gt;")
19
+ end
21
20
 
22
- it "should escape the & character" do
23
- EscapeUtils.escape_html("<b>Bourbon & Branch</b>").should eql("&lt;b&gt;Bourbon &amp; Branch&lt;/b&gt;")
24
- end
21
+ it "should escape the & character" do
22
+ EscapeUtils.escape_html("<b>Bourbon & Branch</b>").should eql("&lt;b&gt;Bourbon &amp; Branch&lt;/b&gt;")
25
23
  end
26
24
  end
@@ -1,26 +1,24 @@
1
1
  # encoding: UTF-8
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
3
3
 
4
- describe EscapeUtils do
4
+ describe EscapeUtils, "unescape_html" do
5
5
  it "should respond to unescape_html" do
6
6
  EscapeUtils.should respond_to(:unescape_html)
7
7
  end
8
8
 
9
- context "unescape_html" do
10
- it "should unescape a basic html tag" do
11
- EscapeUtils.unescape_html("&lt;some_tag/&gt;").should eql("<some_tag/>")
12
- end
9
+ it "should unescape a basic html tag" do
10
+ EscapeUtils.unescape_html("&lt;some_tag/&gt;").should eql("<some_tag/>")
11
+ end
13
12
 
14
- it "should unescape double-quotes" do
15
- EscapeUtils.unescape_html("&lt;some_tag some_attr=&quot;some value&quot;/&gt;").should eql("<some_tag some_attr=\"some value\"/>")
16
- end
13
+ it "should unescape double-quotes" do
14
+ EscapeUtils.unescape_html("&lt;some_tag some_attr=&quot;some value&quot;/&gt;").should eql("<some_tag some_attr=\"some value\"/>")
15
+ end
17
16
 
18
- it "should unescape single-quotes" do
19
- EscapeUtils.unescape_html("&lt;some_tag some_attr=&#39;some value&#39;/&gt;").should eql("<some_tag some_attr='some value'/>")
20
- end
17
+ it "should unescape single-quotes" do
18
+ EscapeUtils.unescape_html("&lt;some_tag some_attr=&#39;some value&#39;/&gt;").should eql("<some_tag some_attr='some value'/>")
19
+ end
21
20
 
22
- it "should unescape the & character" do
23
- EscapeUtils.unescape_html("&lt;b&gt;Bourbon &amp; Branch&lt;/b&gt;").should eql("<b>Bourbon & Branch</b>")
24
- end
21
+ it "should unescape the & character" do
22
+ EscapeUtils.unescape_html("&lt;b&gt;Bourbon &amp; Branch&lt;/b&gt;").should eql("<b>Bourbon & Branch</b>")
25
23
  end
26
24
  end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
3
+
4
+ describe EscapeUtils, "escape_javascript" do
5
+ it "should respond to escape_javascript" do
6
+ EscapeUtils.should respond_to(:escape_javascript)
7
+ end
8
+
9
+ # these are from the ActionView tests
10
+ it "should return an empty string if passed nil" do
11
+ EscapeUtils.escape_javascript(nil).should eql("")
12
+ end
13
+
14
+ it "should escape quotes and newlines" do
15
+ EscapeUtils.escape_javascript(%(This "thing" is really\n netos')).should eql(%(This \\"thing\\" is really\\n netos\\'))
16
+ end
17
+
18
+ it "should escape backslashes" do
19
+ EscapeUtils.escape_javascript(%(backslash\\test)).should eql(%(backslash\\\\test))
20
+ end
21
+
22
+ it "should escape closed html tags" do
23
+ EscapeUtils.escape_javascript(%(dont </close> tags)).should eql(%(dont <\\/close> tags))
24
+ end
25
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Brian Lopez
@@ -33,8 +33,9 @@ files:
33
33
  - README.rdoc
34
34
  - Rakefile
35
35
  - VERSION
36
- - benchmark/escape.rb
37
- - benchmark/unescape.rb
36
+ - benchmark/html_escape.rb
37
+ - benchmark/html_unescape.rb
38
+ - benchmark/javascript_escape.rb
38
39
  - escape_utils.gemspec
39
40
  - ext/escape_utils.c
40
41
  - ext/extconf.rb
@@ -45,6 +46,7 @@ files:
45
46
  - lib/escape_utils/rack.rb
46
47
  - spec/html/escape_spec.rb
47
48
  - spec/html/unescape_spec.rb
49
+ - spec/javascript/escape_spec.rb
48
50
  - spec/rcov.opts
49
51
  - spec/spec.opts
50
52
  - spec/spec_helper.rb
@@ -82,4 +84,5 @@ summary: Faster string escaping routines for your web apps
82
84
  test_files:
83
85
  - spec/html/escape_spec.rb
84
86
  - spec/html/unescape_spec.rb
87
+ - spec/javascript/escape_spec.rb
85
88
  - spec/spec_helper.rb