escape_utils 0.1.8 → 0.1.9
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.
- data/CHANGELOG.md +3 -0
- data/README.rdoc +21 -0
- data/VERSION +1 -1
- data/escape_utils.gemspec +2 -2
- data/ext/escape_utils.c +45 -35
- data/lib/escape_utils.rb +13 -1
- data/lib/escape_utils/html_safety.rb +2 -2
- data/spec/html/escape_spec.rb +11 -1
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.1.9 (October 15th, 2010)
|
4
|
+
* add a flag as an optional 2nd parameter to EscapeUtils.escape_html to disable/enable the escaping of the '/' character. Defaults to the new flag EscapeUtils.html_secure
|
5
|
+
|
3
6
|
## 0.1.8 (September 29th, 2010)
|
4
7
|
* fix URI escaping one last time ;)
|
5
8
|
|
data/README.rdoc
CHANGED
@@ -8,6 +8,8 @@ For character encoding in 1.9, we'll return strings in whatever Encoding.default
|
|
8
8
|
|
9
9
|
It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml and ActionView so you can drop this in and have your app start escaping fast as balls in no time
|
10
10
|
|
11
|
+
It supports HTML, URL, URI and Javascript escaping/unescaping.
|
12
|
+
|
11
13
|
== Installing
|
12
14
|
|
13
15
|
gem install escape_utils
|
@@ -34,6 +36,19 @@ It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml and ActionView so
|
|
34
36
|
require 'escape_utils/html/cgi' # to patch CGI
|
35
37
|
require 'escape_utils/html/haml' # to patch Haml::Helpers
|
36
38
|
|
39
|
+
=== URL
|
40
|
+
|
41
|
+
==== Escaping
|
42
|
+
|
43
|
+
url = "https://www.yourmom.com/cgi-bin/session.cgi?sess_args=mcEA~!!#*YH*>@!U"
|
44
|
+
escaped_url = EscapeUtils.url_escape(url)
|
45
|
+
|
46
|
+
==== Unescaping
|
47
|
+
|
48
|
+
url = "https://www.yourmom.com/cgi-bin/session.cgi?sess_args=mcEA~!!#*YH*>@!U"
|
49
|
+
escaped_url = EscapeUtils.url_escape(url)
|
50
|
+
EscapeUtils.url_unescape(escaped_url) == url # => true
|
51
|
+
|
37
52
|
=== Javascript
|
38
53
|
|
39
54
|
==== Escaping
|
@@ -41,6 +56,12 @@ It has monkey-patches for Rack::Utils, CGI, ERB::Util and Haml and ActionView so
|
|
41
56
|
javascript = `curl -s http://code.jquery.com/jquery-1.4.2.js`
|
42
57
|
escaped_javascript = EscapeUtils.escape_javascript(javascript)
|
43
58
|
|
59
|
+
==== Unescaping
|
60
|
+
|
61
|
+
javascript = `curl -s http://code.jquery.com/jquery-1.4.2.js`
|
62
|
+
escaped_javascript = EscapeUtils.escape_javascript(javascript)
|
63
|
+
EscapeUtils.unescape_javascript(escaped_javascript) == javascript # => true
|
64
|
+
|
44
65
|
==== Monkey Patches
|
45
66
|
|
46
67
|
require 'escape_utils/javascript/action_view' # to patch ActionView::Helpers::JavaScriptHelper
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.9
|
data/escape_utils.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{escape_utils}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.9"
|
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"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-10-15}
|
13
13
|
s.email = %q{seniorlopez@gmail.com}
|
14
14
|
s.extensions = ["ext/extconf.rb"]
|
15
15
|
s.extra_rdoc_files = [
|
data/ext/escape_utils.c
CHANGED
@@ -4,47 +4,43 @@
|
|
4
4
|
static rb_encoding *utf8Encoding;
|
5
5
|
#endif
|
6
6
|
|
7
|
+
static VALUE mEscapeUtils;
|
8
|
+
static ID rb_html_secure;
|
9
|
+
|
7
10
|
#define IS_HEX(c) (c >= 48 || c <= 57) && (c >= 65 || c <= 70) && (c >= 97 || c <= 102)
|
8
11
|
#define NOT_HEX(c) (c < 48 || c > 57) && (c < 65 || c > 90) && (c < 97 || c > 122)
|
9
12
|
#define UNHEX(c) (c >= '0' && c <= '9' ? c - '0' : c >= 'A' && c <= 'F' ? c - 'A' + 10 : c - 'a' + 10)
|
10
13
|
#define URI_SAFE(c) (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c== 45 || c == 46 || c == 95 || c == 126
|
11
14
|
// ALPHA / DIGIT / "-" / "." / "_" / "~"
|
12
15
|
|
13
|
-
static size_t escape_html(unsigned char *out, const unsigned char *in, size_t in_len) {
|
16
|
+
static size_t escape_html(unsigned char *out, const unsigned char *in, size_t in_len, unsigned short int secure) {
|
14
17
|
size_t total = 0;
|
15
18
|
unsigned char curChar;
|
16
19
|
|
17
20
|
total = in_len;
|
18
21
|
while (in_len) {
|
19
22
|
curChar = *in++;
|
20
|
-
|
21
|
-
|
23
|
+
|
24
|
+
if (curChar == '<') {
|
22
25
|
*out++ = '&'; *out++ = 'l'; *out++ = 't'; *out++ = ';';
|
23
26
|
total += 3;
|
24
|
-
|
25
|
-
case '>':
|
27
|
+
} else if (curChar == '>') {
|
26
28
|
*out++ = '&'; *out++ = 'g'; *out++ = 't'; *out++ = ';';
|
27
29
|
total += 3;
|
28
|
-
|
29
|
-
case '&':
|
30
|
+
} else if (curChar == '&') {
|
30
31
|
*out++ = '&'; *out++ = 'a'; *out++ = 'm'; *out++ = 'p'; *out++ = ';';
|
31
32
|
total += 4;
|
32
|
-
|
33
|
-
case '\'':
|
33
|
+
} else if (curChar == '\'') {
|
34
34
|
*out++ = '&'; *out++ = '#'; *out++ = '3'; *out++ = '9'; *out++ = ';';
|
35
35
|
total += 4;
|
36
|
-
|
37
|
-
case '\"':
|
36
|
+
} else if (curChar == '\"') {
|
38
37
|
*out++ = '&'; *out++ = 'q'; *out++ = 'u'; *out++ = 'o'; *out++ = 't'; *out++ = ';';
|
39
38
|
total += 5;
|
40
|
-
|
41
|
-
case '/':
|
39
|
+
} else if (secure && curChar == '/') {
|
42
40
|
*out++ = '&'; *out++ = '#'; *out++ = '4'; *out++ = '7'; *out++ = ';';
|
43
41
|
total += 4;
|
44
|
-
|
45
|
-
default:
|
42
|
+
} else {
|
46
43
|
*out++ = curChar;
|
47
|
-
break;
|
48
44
|
}
|
49
45
|
in_len--;
|
50
46
|
}
|
@@ -282,7 +278,19 @@ static size_t unescape_uri(unsigned char *out, const unsigned char *in, size_t i
|
|
282
278
|
return total;
|
283
279
|
}
|
284
280
|
|
285
|
-
static VALUE rb_escape_html(VALUE
|
281
|
+
static VALUE rb_escape_html(int argc, VALUE * argv, VALUE self) {
|
282
|
+
VALUE str, rb_secure = rb_funcall(mEscapeUtils, rb_html_secure, 0);
|
283
|
+
unsigned short secure = 1;
|
284
|
+
if (rb_secure == Qfalse) {
|
285
|
+
secure = 0;
|
286
|
+
}
|
287
|
+
|
288
|
+
if (rb_scan_args(argc, argv, "11", &str, &rb_secure) == 2) {
|
289
|
+
if (rb_secure == Qfalse) {
|
290
|
+
secure = 0;
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
286
294
|
Check_Type(str, T_STRING);
|
287
295
|
|
288
296
|
VALUE rb_output_buf;
|
@@ -298,7 +306,7 @@ static VALUE rb_escape_html(VALUE self, VALUE str) {
|
|
298
306
|
unsigned char *outBuf = (unsigned char *)malloc(sizeof(unsigned char *)*(len*5));
|
299
307
|
|
300
308
|
// perform our escape, returning the new string's length
|
301
|
-
new_len = escape_html(outBuf, inBuf, len);
|
309
|
+
new_len = escape_html(outBuf, inBuf, len, secure);
|
302
310
|
|
303
311
|
// create our new ruby string
|
304
312
|
rb_output_buf = rb_str_new((char *)outBuf, new_len);
|
@@ -572,26 +580,28 @@ static VALUE rb_unescape_uri(VALUE self, VALUE str) {
|
|
572
580
|
|
573
581
|
/* Ruby Extension initializer */
|
574
582
|
void Init_escape_utils_ext() {
|
575
|
-
|
576
|
-
rb_define_method(
|
577
|
-
rb_define_module_function(
|
578
|
-
rb_define_method(
|
579
|
-
rb_define_module_function(
|
580
|
-
rb_define_method(
|
581
|
-
rb_define_module_function(
|
582
|
-
rb_define_method(
|
583
|
-
rb_define_module_function(
|
584
|
-
rb_define_method(
|
585
|
-
rb_define_module_function(
|
586
|
-
rb_define_method(
|
587
|
-
rb_define_module_function(
|
588
|
-
rb_define_method(
|
589
|
-
rb_define_module_function(
|
590
|
-
rb_define_method(
|
591
|
-
rb_define_module_function(
|
583
|
+
mEscapeUtils = rb_define_module("EscapeUtils");
|
584
|
+
rb_define_method(mEscapeUtils, "escape_html", rb_escape_html, -1);
|
585
|
+
rb_define_module_function(mEscapeUtils, "escape_html", rb_escape_html, -1);
|
586
|
+
rb_define_method(mEscapeUtils, "unescape_html", rb_unescape_html, 1);
|
587
|
+
rb_define_module_function(mEscapeUtils, "unescape_html", rb_unescape_html, 1);
|
588
|
+
rb_define_method(mEscapeUtils, "escape_javascript", rb_escape_javascript, 1);
|
589
|
+
rb_define_module_function(mEscapeUtils, "escape_javascript", rb_escape_javascript, 1);
|
590
|
+
rb_define_method(mEscapeUtils, "unescape_javascript", rb_unescape_javascript, 1);
|
591
|
+
rb_define_module_function(mEscapeUtils, "unescape_javascript", rb_unescape_javascript, 1);
|
592
|
+
rb_define_method(mEscapeUtils, "escape_url", rb_escape_url, 1);
|
593
|
+
rb_define_module_function(mEscapeUtils, "escape_url", rb_escape_url, 1);
|
594
|
+
rb_define_method(mEscapeUtils, "unescape_url", rb_unescape_url, 1);
|
595
|
+
rb_define_module_function(mEscapeUtils, "unescape_url", rb_unescape_url, 1);
|
596
|
+
rb_define_method(mEscapeUtils, "escape_uri", rb_escape_uri, 1);
|
597
|
+
rb_define_module_function(mEscapeUtils, "escape_uri", rb_escape_uri, 1);
|
598
|
+
rb_define_method(mEscapeUtils, "unescape_uri", rb_unescape_uri, 1);
|
599
|
+
rb_define_module_function(mEscapeUtils, "unescape_uri", rb_unescape_uri, 1);
|
592
600
|
|
593
601
|
#ifdef HAVE_RUBY_ENCODING_H
|
594
602
|
utf8Encoding = rb_utf8_encoding();
|
595
603
|
#endif
|
604
|
+
|
605
|
+
rb_html_secure = rb_intern("html_secure");
|
596
606
|
}
|
597
607
|
|
data/lib/escape_utils.rb
CHANGED
@@ -4,7 +4,19 @@ require 'escape_utils_ext'
|
|
4
4
|
|
5
5
|
EscapeUtils.send(:extend, EscapeUtils)
|
6
6
|
module EscapeUtils
|
7
|
-
VERSION = "0.1.
|
7
|
+
VERSION = "0.1.9"
|
8
|
+
|
9
|
+
# turn on/off the escaping of the '/' character during HTML escaping
|
10
|
+
# Escaping '/' is recommended by the OWASP - http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content
|
11
|
+
# This is because quotes around HTML attributes are optional in most/all modern browsers at the time of writing (10/15/2010)
|
12
|
+
@@html_secure = true
|
13
|
+
|
14
|
+
def self.html_secure
|
15
|
+
@@html_secure
|
16
|
+
end
|
17
|
+
def self.html_secure=(val)
|
18
|
+
@@html_secure = val
|
19
|
+
end
|
8
20
|
|
9
21
|
autoload :HtmlSafety, 'escape_utils/html_safety'
|
10
22
|
end
|
@@ -7,12 +7,12 @@ module EscapeUtils
|
|
7
7
|
if s.html_safe?
|
8
8
|
s.to_s.html_safe
|
9
9
|
else
|
10
|
-
EscapeUtils.escape_html(s.to_s).html_safe
|
10
|
+
EscapeUtils.escape_html(s.to_s, EscapeUtils.html_secure).html_safe
|
11
11
|
end
|
12
12
|
end
|
13
13
|
else
|
14
14
|
def _escape_html(s)
|
15
|
-
EscapeUtils.escape_html(s.to_s)
|
15
|
+
EscapeUtils.escape_html(s.to_s, EscapeUtils.html_secure)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
data/spec/html/escape_spec.rb
CHANGED
@@ -6,10 +6,20 @@ describe EscapeUtils, "escape_html" do
|
|
6
6
|
EscapeUtils.should respond_to(:escape_html)
|
7
7
|
end
|
8
8
|
|
9
|
-
it "should escape a basic html tag" do
|
9
|
+
it "should escape a basic html tag, also escaping the '/' character if the secure parameter is true" do
|
10
10
|
EscapeUtils.escape_html("<some_tag/>").should eql("<some_tag/>")
|
11
11
|
end
|
12
12
|
|
13
|
+
it "should escape a basic html tag, not escaping the '/' character if the secure parameter is false" do
|
14
|
+
EscapeUtils.escape_html("<some_tag/>", false).should eql("<some_tag/>")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should escape a basic html tag, not escaping the '/' character if EscapeUtils.html_secure is false" do
|
18
|
+
EscapeUtils.html_secure = false
|
19
|
+
EscapeUtils.escape_html("<some_tag/>").should eql("<some_tag/>")
|
20
|
+
EscapeUtils.html_secure = true
|
21
|
+
end
|
22
|
+
|
13
23
|
it "should escape double-quotes" do
|
14
24
|
EscapeUtils.escape_html("<some_tag some_attr=\"some value\"/>").should eql("<some_tag some_attr="some value"/>")
|
15
25
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escape_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 9
|
10
|
+
version: 0.1.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Brian Lopez
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-15 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|