escape_utils 0.3.1 → 0.3.2
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 +8 -0
- data/ext/escape_utils/escape_utils.c +53 -14
- data/ext/escape_utils/extconf.rb +0 -11
- data/lib/escape_utils.rb +10 -1
- data/lib/escape_utils/version.rb +1 -1
- data/test/html/escape_test.rb +34 -1
- metadata +2 -2
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 0.3.2 (February 28th, 2013)
|
4
|
+
* fix rbx compatibility
|
5
|
+
* add EscapeUtils.html_safe_string_class
|
6
|
+
* add EscapeUtils.escape_html_as_html_safe
|
7
|
+
|
8
|
+
## 0.3.1 (February 26th, 2013)
|
9
|
+
* fixed compilation on Windows
|
10
|
+
|
3
11
|
## 0.3.0 (February 26th, 2013)
|
4
12
|
* add xml escaping support
|
5
13
|
* in Ruby 1.9 - escape_utils now requires the input string be UTF-8
|
@@ -6,10 +6,6 @@
|
|
6
6
|
#include <ruby.h>
|
7
7
|
#include "houdini.h"
|
8
8
|
|
9
|
-
#if RB_CVAR_SET_ARITY == 4
|
10
|
-
# define rb_cvar_set(a,b,c) rb_cvar_set(a,b,c,0)
|
11
|
-
#endif
|
12
|
-
|
13
9
|
#ifdef HAVE_RUBY_ENCODING_H
|
14
10
|
#include <ruby/encoding.h>
|
15
11
|
static VALUE rb_eEncodingCompatibilityError;
|
@@ -48,22 +44,34 @@ static void check_utf8_encoding(VALUE str) {}
|
|
48
44
|
typedef int (*houdini_cb)(gh_buf *, const uint8_t *, size_t);
|
49
45
|
|
50
46
|
static VALUE rb_mEscapeUtils;
|
47
|
+
static ID ID_at_html_safe, ID_new;
|
51
48
|
|
52
49
|
/**
|
53
50
|
* html_secure instance variable
|
54
51
|
*/
|
55
|
-
static ID rb_html_secure;
|
56
52
|
static int g_html_secure = 1;
|
57
53
|
|
58
|
-
static VALUE
|
54
|
+
static VALUE rb_eu_set_html_secure(VALUE self, VALUE val)
|
59
55
|
{
|
60
|
-
|
56
|
+
g_html_secure = RTEST(val);
|
57
|
+
rb_ivar_set(self, rb_intern("@html_secure"), val);
|
58
|
+
return val;
|
61
59
|
}
|
62
60
|
|
63
|
-
|
61
|
+
/**
|
62
|
+
* html_safe_string_class instance variable
|
63
|
+
*/
|
64
|
+
static VALUE rb_html_safe_string_class;
|
65
|
+
|
66
|
+
static VALUE rb_eu_set_html_safe_string_class(VALUE self, VALUE val)
|
64
67
|
{
|
65
|
-
|
66
|
-
|
68
|
+
Check_Type(val, T_CLASS);
|
69
|
+
|
70
|
+
if (rb_funcall(val, rb_intern("<="), 1, rb_cString) == Qnil)
|
71
|
+
rb_raise(rb_eArgError, "%s must be a descendent of String", rb_class2name(val));
|
72
|
+
|
73
|
+
rb_html_safe_string_class = val;
|
74
|
+
rb_ivar_set(self, rb_intern("@html_safe_string_class"), val);
|
67
75
|
return val;
|
68
76
|
}
|
69
77
|
|
@@ -94,6 +102,37 @@ rb_eu__generic(VALUE str, houdini_cb do_escape)
|
|
94
102
|
/**
|
95
103
|
* HTML methods
|
96
104
|
*/
|
105
|
+
static VALUE rb_eu_escape_html_as_html_safe(VALUE self, VALUE str)
|
106
|
+
{
|
107
|
+
VALUE result;
|
108
|
+
int secure = g_html_secure;
|
109
|
+
gh_buf buf = GH_BUF_INIT;
|
110
|
+
|
111
|
+
Check_Type(str, T_STRING);
|
112
|
+
check_utf8_encoding(str);
|
113
|
+
|
114
|
+
if (houdini_escape_html0(&buf, (const uint8_t *)RSTRING_PTR(str), RSTRING_LEN(str), secure)) {
|
115
|
+
result = eu_new_str(buf.ptr, buf.size);
|
116
|
+
gh_buf_free(&buf);
|
117
|
+
} else {
|
118
|
+
#ifdef RBASIC
|
119
|
+
result = rb_str_dup(str);
|
120
|
+
#else
|
121
|
+
result = str;
|
122
|
+
#endif
|
123
|
+
}
|
124
|
+
|
125
|
+
#ifdef RBASIC
|
126
|
+
RBASIC(result)->klass = rb_html_safe_string_class;
|
127
|
+
#else
|
128
|
+
result = rb_funcall(rb_html_safe_string_class, ID_new, 1, result);
|
129
|
+
#endif
|
130
|
+
|
131
|
+
rb_ivar_set(result, ID_at_html_safe, Qtrue);
|
132
|
+
|
133
|
+
return result;
|
134
|
+
}
|
135
|
+
|
97
136
|
static VALUE rb_eu_escape_html(int argc, VALUE *argv, VALUE self)
|
98
137
|
{
|
99
138
|
VALUE str, rb_secure;
|
@@ -181,12 +220,14 @@ static VALUE rb_eu_unescape_uri(VALUE self, VALUE str)
|
|
181
220
|
void Init_escape_utils()
|
182
221
|
{
|
183
222
|
#ifdef HAVE_RUBY_ENCODING_H
|
184
|
-
VALUE rb_cEncoding = rb_const_get(rb_cObject, rb_intern("Encoding"));
|
185
223
|
rb_eEncodingCompatibilityError = rb_const_get(rb_cEncoding, rb_intern("CompatibilityError"));
|
186
224
|
#endif
|
187
225
|
|
226
|
+
ID_new = rb_intern("new");
|
227
|
+
ID_at_html_safe = rb_intern("@html_safe");
|
188
228
|
rb_mEscapeUtils = rb_define_module("EscapeUtils");
|
189
229
|
|
230
|
+
rb_define_method(rb_mEscapeUtils, "escape_html_as_html_safe", rb_eu_escape_html_as_html_safe, 1);
|
190
231
|
rb_define_method(rb_mEscapeUtils, "escape_html", rb_eu_escape_html, -1);
|
191
232
|
rb_define_method(rb_mEscapeUtils, "unescape_html", rb_eu_unescape_html, 1);
|
192
233
|
rb_define_method(rb_mEscapeUtils, "escape_xml", rb_eu_escape_xml, 1);
|
@@ -197,9 +238,7 @@ void Init_escape_utils()
|
|
197
238
|
rb_define_method(rb_mEscapeUtils, "escape_uri", rb_eu_escape_uri, 1);
|
198
239
|
rb_define_method(rb_mEscapeUtils, "unescape_uri", rb_eu_unescape_uri, 1);
|
199
240
|
|
200
|
-
rb_define_singleton_method(rb_mEscapeUtils, "html_secure", rb_eu_get_html_secure, 0);
|
201
241
|
rb_define_singleton_method(rb_mEscapeUtils, "html_secure=", rb_eu_set_html_secure, 1);
|
202
|
-
|
203
|
-
rb_html_secure = rb_intern("@@html_secure");
|
242
|
+
rb_define_singleton_method(rb_mEscapeUtils, "html_safe_string_class=", rb_eu_set_html_safe_string_class, 1);
|
204
243
|
}
|
205
244
|
|
data/ext/escape_utils/extconf.rb
CHANGED
@@ -1,17 +1,6 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
require 'mkmf'
|
3
|
-
require 'rbconfig'
|
4
2
|
|
5
3
|
$CFLAGS << ' -Wall -funroll-loops'
|
6
4
|
$CFLAGS << ' -Wextra -O0 -ggdb3' if ENV['DEBUG']
|
7
5
|
|
8
|
-
if try_compile(<<SRC)
|
9
|
-
#include <ruby.h>
|
10
|
-
int main(void) { rb_cvar_set(Qnil, Qnil, Qnil); return 0; }
|
11
|
-
SRC
|
12
|
-
$CFLAGS << " -DRB_CVAR_SET_ARITY=3 "
|
13
|
-
else
|
14
|
-
$CFLAGS << " -DRB_CVAR_SET_ARITY=4 "
|
15
|
-
end
|
16
|
-
|
17
6
|
create_makefile("escape_utils/escape_utils")
|
data/lib/escape_utils.rb
CHANGED
@@ -7,7 +7,16 @@ module EscapeUtils
|
|
7
7
|
# turn on/off the escaping of the '/' character during HTML escaping
|
8
8
|
# 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
|
9
9
|
# This is because quotes around HTML attributes are optional in most/all modern browsers at the time of writing (10/15/2010)
|
10
|
-
|
10
|
+
def self.html_secure
|
11
|
+
@html_secure
|
12
|
+
end
|
13
|
+
self.html_secure = true
|
14
|
+
|
15
|
+
# Default String class to return from HTML escaping
|
16
|
+
def self.html_safe_string_class
|
17
|
+
@html_safe_string_class
|
18
|
+
end
|
19
|
+
self.html_safe_string_class = String
|
11
20
|
|
12
21
|
autoload :HtmlSafety, 'escape_utils/html_safety'
|
13
22
|
end
|
data/lib/escape_utils/version.rb
CHANGED
data/test/html/escape_test.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require File.expand_path("../../helper", __FILE__)
|
2
2
|
|
3
|
+
class MyCustomHtmlSafeString < String
|
4
|
+
end
|
5
|
+
|
3
6
|
class HtmlEscapeTest < MiniTest::Unit::TestCase
|
4
7
|
def test_escape_basic_html_with_secure
|
5
8
|
assert_equal "<some_tag/>", EscapeUtils.escape_html("<some_tag/>")
|
@@ -36,6 +39,36 @@ class HtmlEscapeTest < MiniTest::Unit::TestCase
|
|
36
39
|
assert_equal str.object_id, EscapeUtils.escape_html(str).object_id
|
37
40
|
end
|
38
41
|
|
42
|
+
def test_html_safe_escape_default_works
|
43
|
+
str = EscapeUtils.escape_html_as_html_safe('foobar')
|
44
|
+
assert_equal 'foobar', str
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_returns_custom_string_class
|
48
|
+
klass_before = EscapeUtils.html_safe_string_class
|
49
|
+
EscapeUtils.html_safe_string_class = MyCustomHtmlSafeString
|
50
|
+
|
51
|
+
str = EscapeUtils.escape_html_as_html_safe('foobar')
|
52
|
+
assert_equal 'foobar', str
|
53
|
+
assert_equal MyCustomHtmlSafeString, str.class
|
54
|
+
assert_equal true, str.instance_variable_get(:@html_safe)
|
55
|
+
ensure
|
56
|
+
EscapeUtils.html_safe_string_class = klass_before
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_html_safe_string_class_descends_string
|
60
|
+
assert_raises ArgumentError do
|
61
|
+
EscapeUtils.html_safe_string_class = Hash
|
62
|
+
end
|
63
|
+
|
64
|
+
begin
|
65
|
+
EscapeUtils.html_safe_string_class = String
|
66
|
+
EscapeUtils.html_safe_string_class = MyCustomHtmlSafeString
|
67
|
+
rescue ArgumentError => e
|
68
|
+
assert_nil e, "#{e.class.name} raised, expected nothing"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
39
72
|
if RUBY_VERSION =~ /^1.9/
|
40
73
|
def test_utf8_or_ascii_input_only
|
41
74
|
str = "<b>Bourbon & Branch</b>"
|
@@ -58,4 +91,4 @@ class HtmlEscapeTest < MiniTest::Unit::TestCase
|
|
58
91
|
assert_equal Encoding.find('UTF-8'), EscapeUtils.escape_html(str).encoding
|
59
92
|
end
|
60
93
|
end
|
61
|
-
end
|
94
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escape_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|