ruby-changes:41147
From: nobu <ko1@a...>
Date: Sun, 20 Dec 2015 20:55:10 +0900 (JST)
Subject: [ruby-changes:41147] nobu:r53220 (trunk): cgi/escape: Optimize CGI.escapeHTML
nobu 2015-12-20 20:54:54 +0900 (Sun, 20 Dec 2015) New Revision: 53220 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=53220 Log: cgi/escape: Optimize CGI.escapeHTML * cgi/escape/escape.c: Optimize CGI.escapeHTML for ASCII-compatible encodings. [Fix GH-1164] Added directories: trunk/ext/cgi/ trunk/ext/cgi/escape/ Added files: trunk/ext/cgi/escape/escape.c trunk/ext/cgi/escape/extconf.rb Modified files: trunk/ChangeLog trunk/ext/Setup trunk/ext/Setup.atheos trunk/ext/Setup.nacl trunk/ext/Setup.nt trunk/lib/cgi/util.rb trunk/test/cgi/test_cgi_util.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 53219) +++ ChangeLog (revision 53220) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun Dec 20 20:54:51 2015 Takashi Kokubun <takashikkbn@g...> + + * cgi/escape/escape.c: Optimize CGI.escapeHTML for + ASCII-compatible encodings. [Fix GH-1164] + Sun Dec 20 15:36:46 2015 SHIBATA Hiroshi <hsbt@r...> * lib/erb.rb: revert r53123. It breaks compatibility like thor and Index: lib/cgi/util.rb =================================================================== --- lib/cgi/util.rb (revision 53219) +++ lib/cgi/util.rb (revision 53220) @@ -38,6 +38,11 @@ module CGI::Util https://github.com/ruby/ruby/blob/trunk/lib/cgi/util.rb#L38 string.gsub(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) end + begin + require 'cgi/escape' + rescue LoadError + end + # Unescape a string that has been HTML-escaped # CGI::unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" <baz>" Index: ext/Setup.nt =================================================================== --- ext/Setup.nt (revision 53219) +++ ext/Setup.nt (revision 53220) @@ -3,6 +3,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/Setup.nt#L3 Win32API bigdecimal +cgi/escape #dbm digest digest/md5 Index: ext/Setup =================================================================== --- ext/Setup (revision 53219) +++ ext/Setup (revision 53220) @@ -1,6 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/Setup#L1 #option nodynamic #bigdecimal +#cgi/escape #continuation #coverage #date Index: ext/cgi/escape/escape.c =================================================================== --- ext/cgi/escape/escape.c (revision 0) +++ ext/cgi/escape/escape.c (revision 53220) @@ -0,0 +1,97 @@ https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/escape.c#L1 +#include "ruby.h" +#include "ruby/encoding.h" + +static VALUE rb_cCGI, rb_mUtil, rb_mEscape; + +static void +html_escaped_cat(VALUE str, char c) +{ + switch (c) { + case '\'': + rb_str_cat_cstr(str, "'"); + break; + case '&': + rb_str_cat_cstr(str, "&"); + break; + case '"': + rb_str_cat_cstr(str, """); + break; + case '<': + rb_str_cat_cstr(str, "<"); + break; + case '>': + rb_str_cat_cstr(str, ">"); + break; + } +} + +static VALUE +optimized_escape_html(VALUE str) +{ + long i, len, modified = 0, beg = 0; + VALUE dest; + const char *cstr; + + len = RSTRING_LEN(str); + cstr = RSTRING_PTR(str); + + for (i = 0; i < len; i++) { + switch (cstr[i]) { + case '\'': + case '&': + case '"': + case '<': + case '>': + if (!modified) { + modified = 1; + dest = rb_str_buf_new(len); + } + + rb_str_cat(dest, cstr + beg, i - beg); + beg = i + 1; + + html_escaped_cat(dest, cstr[i]); + break; + } + } + + if (modified) { + rb_str_cat(dest, cstr + beg, len - beg); + rb_enc_associate(dest, rb_enc_get(str)); + return dest; + } + else { + return str; + } +} + +/* + * call-seq: + * CGI.escapeHTML(string) -> string + * + * Returns HTML-escaped string. + * + */ +static VALUE +cgiesc_escape_html(VALUE self, VALUE str) +{ + StringValue(str); + + if (rb_enc_str_asciicompat_p(str)) { + return optimized_escape_html(str); + } + else { + return rb_call_super(1, &str); + } +} + +void +Init_escape(void) +{ + rb_cCGI = rb_define_class("CGI", rb_cObject); + rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); + rb_mUtil = rb_define_module_under(rb_cCGI, "Util"); + rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1); + rb_prepend_module(rb_mUtil, rb_mEscape); + rb_extend_object(rb_cCGI, rb_mEscape); +} Property changes on: ext/cgi/escape/escape.c ___________________________________________________________________ Added: svn:eol-style + LF Index: ext/cgi/escape/extconf.rb =================================================================== --- ext/cgi/escape/extconf.rb (revision 0) +++ ext/cgi/escape/extconf.rb (revision 53220) @@ -0,0 +1,3 @@ https://github.com/ruby/ruby/blob/trunk/ext/cgi/escape/extconf.rb#L1 +require 'mkmf' + +create_makefile 'cgi/escape' Property changes on: ext/cgi/escape/extconf.rb ___________________________________________________________________ Added: svn:eol-style + LF Index: ext/Setup.nacl =================================================================== --- ext/Setup.nacl (revision 53219) +++ ext/Setup.nacl (revision 53220) @@ -2,6 +2,7 @@ https://github.com/ruby/ruby/blob/trunk/ext/Setup.nacl#L2 # # #Win32API # bigdecimal +# cgi/escape # continuation # coverage # date Index: ext/Setup.atheos =================================================================== --- ext/Setup.atheos (revision 53219) +++ ext/Setup.atheos (revision 53220) @@ -2,6 +2,7 @@ option nodynamic https://github.com/ruby/ruby/blob/trunk/ext/Setup.atheos#L2 #Win32API bigdecimal +cgi/escape dbm digest digest/md5 Index: test/cgi/test_cgi_util.rb =================================================================== --- test/cgi/test_cgi_util.rb (revision 53219) +++ test/cgi/test_cgi_util.rb (revision 53220) @@ -62,6 +62,12 @@ class CGIUtilTest < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/cgi/test_cgi_util.rb#L62 assert_equal("'&"><", CGI::escapeHTML("'&\"><")) end + def test_cgi_escape_html_preserve_encoding + assert_equal(Encoding::US_ASCII, CGI::escapeHTML("'&\"><".force_encoding("US-ASCII")).encoding) + assert_equal(Encoding::ASCII_8BIT, CGI::escapeHTML("'&\"><".force_encoding("ASCII-8BIT")).encoding) + assert_equal(Encoding::UTF_8, CGI::escapeHTML("'&\"><".force_encoding("UTF-8")).encoding) + end + def test_cgi_unescapeHTML assert_equal("'&\"><", CGI::unescapeHTML("'&"><")) end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/