diff --git a/ext/escape_utils/escape_utils.c b/ext/escape_utils/escape_utils.c index fb43e3c..453ca06 100644 --- a/ext/escape_utils/escape_utils.c +++ b/ext/escape_utils/escape_utils.c @@ -188,6 +188,13 @@ static VALUE rb_eu_unescape_url(VALUE self, VALUE str) return rb_eu__generic(str, &houdini_unescape_url); } +/** + * HREF methods + */ +static VALUE rb_eu_escape_href(VALUE self, VALUE str) +{ + return rb_eu__generic(str, &houdini_escape_href); +} /** * URI methods @@ -236,6 +243,7 @@ void Init_escape_utils() rb_define_method(rb_mEscapeUtils, "escape_xml", rb_eu_escape_xml, 1); rb_define_method(rb_mEscapeUtils, "escape_javascript", rb_eu_escape_js, 1); rb_define_method(rb_mEscapeUtils, "unescape_javascript", rb_eu_unescape_js, 1); + rb_define_method(rb_mEscapeUtils, "escape_href", rb_eu_escape_href, 1); rb_define_method(rb_mEscapeUtils, "escape_url", rb_eu_escape_url, 1); rb_define_method(rb_mEscapeUtils, "unescape_url", rb_eu_unescape_url, 1); rb_define_method(rb_mEscapeUtils, "escape_uri", rb_eu_escape_uri, 1); diff --git a/test/href/escape_test.rb b/test/href/escape_test.rb new file mode 100644 index 0000000..c7d353d --- /dev/null +++ b/test/href/escape_test.rb @@ -0,0 +1,59 @@ +require File.expand_path("../../helper", __FILE__) +require 'cgi' + +class HrefEscapeTest < Minitest::Test + def test_basic_href + assert_equal "http://www.homerun.com/", EscapeUtils.escape_href("http://www.homerun.com/") + end + + def test_href_containing_tags + assert_equal "fo%3Co%3Ebar", EscapeUtils.escape_href("fobar") + end + + def test_href_containing_spaces + assert_equal "a%20space", EscapeUtils.escape_href("a space") + assert_equal "a%20%20%20sp%20ace%20", EscapeUtils.escape_href("a sp ace ") + end + + def test_href_containing_mixed_characters + assert_equal "q1!2%22'w$5&7/z8)?%5C", EscapeUtils.escape_href("q1!2\"'w$5&7/z8)?\\") + end + + def test_multibyte_characters + matz_name = "\xE3\x81\xBE\xE3\x81\xA4\xE3\x82\x82\xE3\x81\xA8" # Matsumoto + assert_equal '%E3%81%BE%E3%81%A4%E3%82%82%E3%81%A8', EscapeUtils.escape_href(matz_name) + matz_name_sep = "\xE3\x81\xBE\xE3\x81\xA4 \xE3\x82\x82\xE3\x81\xA8" # Matsu moto + assert_equal '%E3%81%BE%E3%81%A4%20%E3%82%82%E3%81%A8', EscapeUtils.escape_href(matz_name_sep) + end + + def test_href_containing_pluses + assert_equal "a+plus", EscapeUtils.escape_href("a+plus") + end + + def test_href_containing_slashes + assert_equal "a/slash", EscapeUtils.escape_href("a/slash") + end + + if RUBY_VERSION =~ /^1.9/ + def test_input_must_be_utf8_or_ascii + str = "fobar" + + str.force_encoding 'ISO-8859-1' + assert_raises Encoding::CompatibilityError do + EscapeUtils.escape_href(str) + end + + str.force_encoding 'UTF-8' + begin + EscapeUtils.escape_href(str) + rescue Encoding::CompatibilityError => e + assert_nil e, "#{e.class.name} raised, expected not to" + end + end + + def test_return_value_is_tagged_as_utf8 + str = "fobar" + assert_equal Encoding.find('UTF-8'), EscapeUtils.escape_href(str).encoding + end + end +end