From: Gaston Ramos Date: 2009-12-18T10:00:43+09:00 Subject: [ruby-core:27213] Re: [PATCH] fix CGI::escape to work with blocks, avoid dollar variables El Thu, 17 de Dec de 2009, a las 09:53:37PM +0900, NARUSE, Yui dijo: > > I mean, your stating point: allow overriding String#gsub. > Even if you fix cgi.rb, other problem will happen. What other problem ? can you give me an example? I give you an example that show you when the current version of cgi has problems. Did you read this ticket? is other case when the current cgi doesn't work and the problem is related with dollar variable. http://rails.lighthouseapp.com/projects/8994/tickets/3475-activesupportmultibytecharsgsub-fails-while-stringgsub-works How do know that your patch is twice faster than the current implementation? can you show the benchmark? Thanks. > > > Anyway, following patch is twice faster than current implementation > and doesn't use dollar variables. > > diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb > index 42f1336..c2cc495 100644 > --- a/lib/cgi/util.rb > +++ b/lib/cgi/util.rb > @@ -1,24 +1,198 @@ > class CGI > @@accept_charset="UTF-8" unless defined?(@@accept_charset) > + > + TABLE_FOR_URLENCODE__ = { > + "\x00" => "%00", "\x01" => "%01", "\x02" => "%02", "\x03" => "%03", > + "\x04" => "%04", "\x05" => "%05", "\x06" => "%06", "\x07" => "%07", > + "\x08" => "%08", "\x09" => "%09", "\x0A" => "%0A", "\x0B" => "%0B", > + "\x0C" => "%0C", "\x0D" => "%0D", "\x0E" => "%0E", "\x0F" => "%0F", > + "\x10" => "%10", "\x11" => "%11", "\x12" => "%12", "\x13" => "%13", > + "\x14" => "%14", "\x15" => "%15", "\x16" => "%16", "\x17" => "%17", > + "\x18" => "%18", "\x19" => "%19", "\x1A" => "%1A", "\x1B" => "%1B", > + "\x1C" => "%1C", "\x1D" => "%1D", "\x1E" => "%1E", "\x1F" => "%1F", > + " " => "+", "!" => "%21", '"' => "%22", "#" => "%23", > + "$" => "%24", "%" => "%25", "&" => "%26", "'" => "%27", > + "(" => "%28", ")" => "%29", "*" => "%2A", "+" => "%2B", > + "," => "%2C", "-" => "%2D", "." => "%2E", "/" => "%2F", > + ":" => "%3A", ";" => "%3B", "<" => "%3C", "=" => "%3D", > + ">" => "%3E", "?" => "%3F", "@" => "%40", "[" => "%5B", > + "\\" => "%5C", "]" => "%5D", "^" => "%5E", "_" => "%5F", > + "`" => "%60", "{" => "%7B", > + "|" => "%7C", "}" => "%7D", "~" => "%7E", "\x7F" => "%7F", > + "\x80" => "%80", "\x81" => "%81", "\x82" => "%82", "\x83" => "%83", > + "\x84" => "%84", "\x85" => "%85", "\x86" => "%86", "\x87" => "%87", > + "\x88" => "%88", "\x89" => "%89", "\x8A" => "%8A", "\x8B" => "%8B", > + "\x8C" => "%8C", "\x8D" => "%8D", "\x8E" => "%8E", "\x8F" => "%8F", > + "\x90" => "%90", "\x91" => "%91", "\x92" => "%92", "\x93" => "%93", > + "\x94" => "%94", "\x95" => "%95", "\x96" => "%96", "\x97" => "%97", > + "\x98" => "%98", "\x99" => "%99", "\x9A" => "%9A", "\x9B" => "%9B", > + "\x9C" => "%9C", "\x9D" => "%9D", "\x9E" => "%9E", "\x9F" => "%9F", > + "\xA0" => "%A0", "\xA1" => "%A1", "\xA2" => "%A2", "\xA3" => "%A3", > + "\xA4" => "%A4", "\xA5" => "%A5", "\xA6" => "%A6", "\xA7" => "%A7", > + "\xA8" => "%A8", "\xA9" => "%A9", "\xAA" => "%AA", "\xAB" => "%AB", > + "\xAC" => "%AC", "\xAD" => "%AD", "\xAE" => "%AE", "\xAF" => "%AF", > + "\xB0" => "%B0", "\xB1" => "%B1", "\xB2" => "%B2", "\xB3" => "%B3", > + "\xB4" => "%B4", "\xB5" => "%B5", "\xB6" => "%B6", "\xB7" => "%B7", > + "\xB8" => "%B8", "\xB9" => "%B9", "\xBA" => "%BA", "\xBB" => "%BB", > + "\xBC" => "%BC", "\xBD" => "%BD", "\xBE" => "%BE", "\xBF" => "%BF", > + "\xC0" => "%C0", "\xC1" => "%C1", "\xC2" => "%C2", "\xC3" => "%C3", > + "\xC4" => "%C4", "\xC5" => "%C5", "\xC6" => "%C6", "\xC7" => "%C7", > + "\xC8" => "%C8", "\xC9" => "%C9", "\xCA" => "%CA", "\xCB" => "%CB", > + "\xCC" => "%CC", "\xCD" => "%CD", "\xCE" => "%CE", "\xCF" => "%CF", > + "\xD0" => "%D0", "\xD1" => "%D1", "\xD2" => "%D2", "\xD3" => "%D3", > + "\xD4" => "%D4", "\xD5" => "%D5", "\xD6" => "%D6", "\xD7" => "%D7", > + "\xD8" => "%D8", "\xD9" => "%D9", "\xDA" => "%DA", "\xDB" => "%DB", > + "\xDC" => "%DC", "\xDD" => "%DD", "\xDE" => "%DE", "\xDF" => "%DF", > + "\xE0" => "%E0", "\xE1" => "%E1", "\xE2" => "%E2", "\xE3" => "%E3", > + "\xE4" => "%E4", "\xE5" => "%E5", "\xE6" => "%E6", "\xE7" => "%E7", > + "\xE8" => "%E8", "\xE9" => "%E9", "\xEA" => "%EA", "\xEB" => "%EB", > + "\xEC" => "%EC", "\xED" => "%ED", "\xEE" => "%EE", "\xEF" => "%EF", > + "\xF0" => "%F0", "\xF1" => "%F1", "\xF2" => "%F2", "\xF3" => "%F3", > + "\xF4" => "%F4", "\xF5" => "%F5", "\xF6" => "%F6", "\xF7" => "%F7", > + "\xF8" => "%F8", "\xF9" => "%F9", "\xFA" => "%FA", "\xFB" => "%FB", > + "\xFC" => "%FC", "\xFD" => "%FD", "\xFE" => "%FE", "\xFF" => "%FF"} > + > # URL-encode a string. > # url_encoded_string = CGI::escape("'Stop!' said Fred") > # # => "%27Stop%21%27+said+Fred" > def CGI::escape(string) > - string.gsub(/([^ a-zA-Z0-9_.-]+)/) do > - '%' + $1.unpack('H2' * $1.bytesize).join('%').upcase > - end.tr(' ', '+') > + str = string.dup.force_encoding(Encoding::ASCII_8BIT) > + str.gsub!(/[^a-zA-Z0-9_.-]/, TABLE_FOR_URLENCODE__) > + str.force_encoding(Encoding::US_ASCII) > end > > + TABLE_FOR_URLDECODE__ = { > + "%00" => "\x00", "%01" => "\x01", "%02" => "\x02", "%03" => "\x03", > + "%04" => "\x04", "%05" => "\x05", "%06" => "\x06", "%07" => "\a", > + "%08" => "\b", "%09" => "\t", "%0a" => "\n", "%0A" => "\n", > + "%0b" => "\v", "%0B" => "\v", "%0c" => "\f", "%0C" => "\f", > + "%0d" => "\r", "%0D" => "\r", "%0e" => "\x0E", "%0E" => "\x0E", > + "%0f" => "\x0F", "%0F" => "\x0F", "%10" => "\x10", "%11" => "\x11", > + "%12" => "\x12", "%13" => "\x13", "%14" => "\x14", "%15" => "\x15", > + "%16" => "\x16", "%17" => "\x17", "%18" => "\x18", "%19" => "\x19", > + "%1a" => "\x1A", "%1A" => "\x1A", "%1b" => "\e", "%1B" => "\e", > + "%1c" => "\x1C", "%1C" => "\x1C", "%1d" => "\x1D", "%1D" => "\x1D", > + "%1e" => "\x1E", "%1E" => "\x1E", "%1f" => "\x1F", "%1F" => "\x1F", > + "%20" => " ", "%21" => "!", "%22" => "\"", "%23" => "#", > + "%24" => "$", "%25" => "%", "%26" => "&", "%27" => "'", > + "%28" => "(", "%29" => ")", "%2a" => "*", "%2A" => "*", > + "%2b" => "+", "%2B" => "+", "%2c" => ",", "%2C" => ",", > + "%2d" => "-", "%2D" => "-", "%2e" => ".", "%2E" => ".", > + "%2f" => "/", "%2F" => "/", "%30" => "0", "%31" => "1", > + "%32" => "2", "%33" => "3", "%34" => "4", "%35" => "5", > + "%36" => "6", "%37" => "7", "%38" => "8", "%39" => "9", > + "%3a" => ":", "%3A" => ":", "%3b" => ";", "%3B" => ";", > + "%3c" => "<", "%3C" => "<", "%3d" => "=", "%3D" => "=", > + "%3e" => ">", "%3E" => ">", "%3f" => "?", "%3F" => "?", > + "%40" => "@", "%41" => "A", "%42" => "B", "%43" => "C", > + "%44" => "D", "%45" => "E", "%46" => "F", "%47" => "G", > + "%48" => "H", "%49" => "I", "%4a" => "J", "%4A" => "J", > + "%4b" => "K", "%4B" => "K", "%4c" => "L", "%4C" => "L", > + "%4d" => "M", "%4D" => "M", "%4e" => "N", "%4E" => "N", > + "%4f" => "O", "%4F" => "O", "%50" => "P", "%51" => "Q", > + "%52" => "R", "%53" => "S", "%54" => "T", "%55" => "U", > + "%56" => "V", "%57" => "W", "%58" => "X", "%59" => "Y", > + "%5a" => "Z", "%5A" => "Z", "%5b" => "[", "%5B" => "[", > + "%5c" => "\\", "%5C" => "\\", "%5d" => "]", "%5D" => "]", > + "%5e" => "^", "%5E" => "^", "%5f" => "_", "%5F" => "_", > + "%60" => "`", "%61" => "a", "%62" => "b", "%63" => "c", > + "%64" => "d", "%65" => "e", "%66" => "f", "%67" => "g", > + "%68" => "h", "%69" => "i", "%6a" => "j", "%6A" => "j", > + "%6b" => "k", "%6B" => "k", "%6c" => "l", "%6C" => "l", > + "%6d" => "m", "%6D" => "m", "%6e" => "n", "%6E" => "n", > + "%6f" => "o", "%6F" => "o", "%70" => "p", "%71" => "q", > + "%72" => "r", "%73" => "s", "%74" => "t", "%75" => "u", > + "%76" => "v", "%77" => "w", "%78" => "x", "%79" => "y", > + "%7a" => "z", "%7A" => "z", "%7b" => "{", "%7B" => "{", > + "%7c" => "|", "%7C" => "|", "%7d" => "}", "%7D" => "}", > + "%7e" => "~", "%7E" => "~", "%7f" => "\x7F", "%7F" => "\x7F", > + "%80" => "\x80", "%81" => "\x81", "%82" => "\x82", "%83" => "\x83", > + "%84" => "\x84", "%85" => "\x85", "%86" => "\x86", "%87" => "\x87", > + "%88" => "\x88", "%89" => "\x89", "%8a" => "\x8A", "%8A" => "\x8A", > + "%8b" => "\x8B", "%8B" => "\x8B", "%8c" => "\x8C", "%8C" => "\x8C", > + "%8d" => "\x8D", "%8D" => "\x8D", "%8e" => "\x8E", "%8E" => "\x8E", > + "%8f" => "\x8F", "%8F" => "\x8F", "%90" => "\x90", "%91" => "\x91", > + "%92" => "\x92", "%93" => "\x93", "%94" => "\x94", "%95" => "\x95", > + "%96" => "\x96", "%97" => "\x97", "%98" => "\x98", "%99" => "\x99", > + "%9a" => "\x9A", "%9A" => "\x9A", "%9b" => "\x9B", "%9B" => "\x9B", > + "%9c" => "\x9C", "%9C" => "\x9C", "%9d" => "\x9D", "%9D" => "\x9D", > + "%9e" => "\x9E", "%9E" => "\x9E", "%9f" => "\x9F", "%9F" => "\x9F", > + "%a0" => "\xA0", "%a1" => "\xA1", "%a2" => "\xA2", "%a3" => "\xA3", > + "%a4" => "\xA4", "%a5" => "\xA5", "%a6" => "\xA6", "%a7" => "\xA7", > + "%a8" => "\xA8", "%a9" => "\xA9", "%aa" => "\xAA", "%aA" => "\xAA", > + "%ab" => "\xAB", "%aB" => "\xAB", "%ac" => "\xAC", "%aC" => "\xAC", > + "%ad" => "\xAD", "%aD" => "\xAD", "%ae" => "\xAE", "%aE" => "\xAE", > + "%af" => "\xAF", "%aF" => "\xAF", "%A0" => "\xA0", "%A1" => "\xA1", > + "%A2" => "\xA2", "%A3" => "\xA3", "%A4" => "\xA4", "%A5" => "\xA5", > + "%A6" => "\xA6", "%A7" => "\xA7", "%A8" => "\xA8", "%A9" => "\xA9", > + "%Aa" => "\xAA", "%AA" => "\xAA", "%Ab" => "\xAB", "%AB" => "\xAB", > + "%Ac" => "\xAC", "%AC" => "\xAC", "%Ad" => "\xAD", "%AD" => "\xAD", > + "%Ae" => "\xAE", "%AE" => "\xAE", "%Af" => "\xAF", "%AF" => "\xAF", > + "%b0" => "\xB0", "%b1" => "\xB1", "%b2" => "\xB2", "%b3" => "\xB3", > + "%b4" => "\xB4", "%b5" => "\xB5", "%b6" => "\xB6", "%b7" => "\xB7", > + "%b8" => "\xB8", "%b9" => "\xB9", "%ba" => "\xBA", "%bA" => "\xBA", > + "%bb" => "\xBB", "%bB" => "\xBB", "%bc" => "\xBC", "%bC" => "\xBC", > + "%bd" => "\xBD", "%bD" => "\xBD", "%be" => "\xBE", "%bE" => "\xBE", > + "%bf" => "\xBF", "%bF" => "\xBF", "%B0" => "\xB0", "%B1" => "\xB1", > + "%B2" => "\xB2", "%B3" => "\xB3", "%B4" => "\xB4", "%B5" => "\xB5", > + "%B6" => "\xB6", "%B7" => "\xB7", "%B8" => "\xB8", "%B9" => "\xB9", > + "%Ba" => "\xBA", "%BA" => "\xBA", "%Bb" => "\xBB", "%BB" => "\xBB", > + "%Bc" => "\xBC", "%BC" => "\xBC", "%Bd" => "\xBD", "%BD" => "\xBD", > + "%Be" => "\xBE", "%BE" => "\xBE", "%Bf" => "\xBF", "%BF" => "\xBF", > + "%c0" => "\xC0", "%c1" => "\xC1", "%c2" => "\xC2", "%c3" => "\xC3", > + "%c4" => "\xC4", "%c5" => "\xC5", "%c6" => "\xC6", "%c7" => "\xC7", > + "%c8" => "\xC8", "%c9" => "\xC9", "%ca" => "\xCA", "%cA" => "\xCA", > + "%cb" => "\xCB", "%cB" => "\xCB", "%cc" => "\xCC", "%cC" => "\xCC", > + "%cd" => "\xCD", "%cD" => "\xCD", "%ce" => "\xCE", "%cE" => "\xCE", > + "%cf" => "\xCF", "%cF" => "\xCF", "%C0" => "\xC0", "%C1" => "\xC1", > + "%C2" => "\xC2", "%C3" => "\xC3", "%C4" => "\xC4", "%C5" => "\xC5", > + "%C6" => "\xC6", "%C7" => "\xC7", "%C8" => "\xC8", "%C9" => "\xC9", > + "%Ca" => "\xCA", "%CA" => "\xCA", "%Cb" => "\xCB", "%CB" => "\xCB", > + "%Cc" => "\xCC", "%CC" => "\xCC", "%Cd" => "\xCD", "%CD" => "\xCD", > + "%Ce" => "\xCE", "%CE" => "\xCE", "%Cf" => "\xCF", "%CF" => "\xCF", > + "%d0" => "\xD0", "%d1" => "\xD1", "%d2" => "\xD2", "%d3" => "\xD3", > + "%d4" => "\xD4", "%d5" => "\xD5", "%d6" => "\xD6", "%d7" => "\xD7", > + "%d8" => "\xD8", "%d9" => "\xD9", "%da" => "\xDA", "%dA" => "\xDA", > + "%db" => "\xDB", "%dB" => "\xDB", "%dc" => "\xDC", "%dC" => "\xDC", > + "%dd" => "\xDD", "%dD" => "\xDD", "%de" => "\xDE", "%dE" => "\xDE", > + "%df" => "\xDF", "%dF" => "\xDF", "%D0" => "\xD0", "%D1" => "\xD1", > + "%D2" => "\xD2", "%D3" => "\xD3", "%D4" => "\xD4", "%D5" => "\xD5", > + "%D6" => "\xD6", "%D7" => "\xD7", "%D8" => "\xD8", "%D9" => "\xD9", > + "%Da" => "\xDA", "%DA" => "\xDA", "%Db" => "\xDB", "%DB" => "\xDB", > + "%Dc" => "\xDC", "%DC" => "\xDC", "%Dd" => "\xDD", "%DD" => "\xDD", > + "%De" => "\xDE", "%DE" => "\xDE", "%Df" => "\xDF", "%DF" => "\xDF", > + "%e0" => "\xE0", "%e1" => "\xE1", "%e2" => "\xE2", "%e3" => "\xE3", > + "%e4" => "\xE4", "%e5" => "\xE5", "%e6" => "\xE6", "%e7" => "\xE7", > + "%e8" => "\xE8", "%e9" => "\xE9", "%ea" => "\xEA", "%eA" => "\xEA", > + "%eb" => "\xEB", "%eB" => "\xEB", "%ec" => "\xEC", "%eC" => "\xEC", > + "%ed" => "\xED", "%eD" => "\xED", "%ee" => "\xEE", "%eE" => "\xEE", > + "%ef" => "\xEF", "%eF" => "\xEF", "%E0" => "\xE0", "%E1" => "\xE1", > + "%E2" => "\xE2", "%E3" => "\xE3", "%E4" => "\xE4", "%E5" => "\xE5", > + "%E6" => "\xE6", "%E7" => "\xE7", "%E8" => "\xE8", "%E9" => "\xE9", > + "%Ea" => "\xEA", "%EA" => "\xEA", "%Eb" => "\xEB", "%EB" => "\xEB", > + "%Ec" => "\xEC", "%EC" => "\xEC", "%Ed" => "\xED", "%ED" => "\xED", > + "%Ee" => "\xEE", "%EE" => "\xEE", "%Ef" => "\xEF", "%EF" => "\xEF", > + "%f0" => "\xF0", "%f1" => "\xF1", "%f2" => "\xF2", "%f3" => "\xF3", > + "%f4" => "\xF4", "%f5" => "\xF5", "%f6" => "\xF6", "%f7" => "\xF7", > + "%f8" => "\xF8", "%f9" => "\xF9", "%fa" => "\xFA", "%fA" => "\xFA", > + "%fb" => "\xFB", "%fB" => "\xFB", "%fc" => "\xFC", "%fC" => "\xFC", > + "%fd" => "\xFD", "%fD" => "\xFD", "%fe" => "\xFE", "%fE" => "\xFE", > + "%ff" => "\xFF", "%fF" => "\xFF", "%F0" => "\xF0", "%F1" => "\xF1", > + "%F2" => "\xF2", "%F3" => "\xF3", "%F4" => "\xF4", "%F5" => "\xF5", > + "%F6" => "\xF6", "%F7" => "\xF7", "%F8" => "\xF8", "%F9" => "\xF9", > + "%Fa" => "\xFA", "%FA" => "\xFA", "%Fb" => "\xFB", "%FB" => "\xFB", > + "%Fc" => "\xFC", "%FC" => "\xFC", "%Fd" => "\xFD", "%FD" => "\xFD", > + "%Fe" => "\xFE", "%FE" => "\xFE", "%Ff" => "\xFF", "%FF" => "\xFF", > + "+" => " "} > > - # URL-decode a string with encoding(optional). > - # string = CGI::unescape("%27Stop%21%27+said+Fred") > - # # => "'Stop!' said Fred" > - def CGI::unescape(string,encoding=@@accept_charset) > - str=string.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/) do > - [$1.delete('%')].pack('H*') > - end.force_encoding(encoding) > - str.valid_encoding? ? str : str.force_encoding(string.encoding) > - end > + # URL-decode a string with encoding(optional). > + # string = CGI::unescape("%27Stop%21%27+said+Fred") > + # # => "'Stop!' said Fred" > + def CGI::unescape(string,encoding=@@accept_charset) > + str = string.gsub(/%[0-9a-fA-F]{2}|\+/, TABLE_FOR_URLDECODE__). > + force_encoding(encoding) > + str.valid_encoding? ? str : str.force_encoding(string.encoding) > + end > > TABLE_FOR_ESCAPE_HTML__ = { > '&' => '&', > > -- > NARUSE, Yui > --