diff --git a/lib/cgi/escape.rb b/lib/cgi/escape.rb index 8668ab4..bdcdcdf 100644 --- a/lib/cgi/escape.rb +++ b/lib/cgi/escape.rb @@ -18,6 +18,7 @@ module CGI::Escape # url_encoded_string = CGI.escape("'Stop!' said Fred") # # => "%27Stop%21%27+said+Fred" def escape(string) + string = string_value(string) encoding = string.encoding buffer = string.b buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m| @@ -31,6 +32,7 @@ def escape(string) # string = CGI.unescape("%27Stop%21%27+said+Fred") # # => "'Stop!' said Fred" def unescape(string, encoding = @@accept_charset) + string = string_value(string) str = string.tr('+', ' ') str = str.b str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| @@ -45,6 +47,7 @@ def unescape(string, encoding = @@accept_charset) # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred") # # => "%27Stop%21%27%20said%20Fred" def escapeURIComponent(string) + string = string_value(string) encoding = string.encoding buffer = string.b buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m| @@ -58,6 +61,7 @@ def escapeURIComponent(string) # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred") # # => "'Stop!'+said Fred" def unescapeURIComponent(string, encoding = @@accept_charset) + string = string_value(string) str = string.b str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| [m.delete('%')].pack('H*') @@ -81,6 +85,7 @@ def unescapeURIComponent(string, encoding = @@accept_charset) # CGI.escapeHTML('Usage: foo "bar" ') # # => "Usage: foo "bar" <baz>" def escapeHTML(string) + string = string_value(string) enc = string.encoding unless enc.ascii_compatible? if enc.dummy? @@ -103,6 +108,7 @@ def escapeHTML(string) # CGI.unescapeHTML("Usage: foo "bar" <baz>") # # => "Usage: foo \"bar\" " def unescapeHTML(string) + string = string_value(string) enc = string.encoding unless enc.ascii_compatible? if enc.dummy? @@ -224,4 +230,10 @@ def unescapeElement(string, *elements) # Synonym for CGI.unescapeElement(str) alias unescape_element unescapeElement + private + + # Like StringValue in C + def string_value(input) # :nodoc: + String.try_convert(input) || raise(TypeError, "no implicit conversion of #{input.class} into String") + end end diff --git a/test/cgi/test_cgi_escape.rb b/test/cgi/test_cgi_escape.rb index fa08953..f614e7f 100644 --- a/test/cgi/test_cgi_escape.rb +++ b/test/cgi/test_cgi_escape.rb @@ -44,6 +44,16 @@ def test_cgi_escape_preserve_encoding assert_equal(Encoding::UTF_8, CGI.escape("\xC0\<\<".dup.force_encoding("UTF-8")).encoding) end + def test_cgi_escape_nil + assert_raise(TypeError) { CGI.escape(nil) } + end + + def test_cgi_escape_conversion + obj = Object.new + def obj.to_str = "foo" + assert_equal("foo", CGI.escape(obj)) + end + def test_cgi_unescape str = CGI.unescape('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93') assert_equal(@str1, str) @@ -69,6 +79,10 @@ def test_cgi_unescape_accept_charset end; end + def test_cgi_unescape_nil + assert_raise(TypeError) { CGI.unescape(nil) } + end + def test_cgi_escapeURIComponent assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escapeURIComponent(@str1)) assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escapeURIComponent(@str1).ascii_only?) if defined?(::Encoding) @@ -94,6 +108,10 @@ def test_cgi_escapeURIComponent_preserve_encoding assert_equal(Encoding::UTF_8, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")).encoding) end + def test_cgi_escapeURIComponent_nil + assert_raise(TypeError) { CGI.escapeURIComponent(nil) } + end + def test_cgi_unescapeURIComponent str = CGI.unescapeURIComponent('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93') assert_equal(@str1, str) @@ -126,6 +144,10 @@ def test_cgi_unescapeURIComponent_accept_charset end; end + def test_cgi_unescapeURIComponent_nil + assert_raise(TypeError) { CGI.unescapeURIComponent(nil) } + end + def test_cgi_escapeHTML assert_equal("'&"><", CGI.escapeHTML("'&\"><")) end @@ -155,6 +177,10 @@ def test_cgi_escape_html_dont_freeze assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen? end + def test_cgi_escape_html_nil + assert_raise(TypeError) { CGI.escapeHTML(nil) } + end + def test_cgi_escape_html_large return if RUBY_ENGINE == 'jruby' ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX") @@ -246,6 +272,10 @@ def test_cgi_unescapeHTML_charref_preserve_encoding assert_equal(enc, result.encoding, name) end end + + def test_cgi_unescapeHTML_nil + assert_raise(TypeError) { CGI.unescapeHTML(nil) } + end end include UnescapeHTMLTests