From 091171a28654801c533166d1819ec7e1705a53ac Mon Sep 17 00:00:00 2001 From: akr Date: Sat, 6 Sep 2008 03:20:51 +0000 Subject: [PATCH] * enc/trans/escape.trans (escape_html_attr_init): new function. (fun_so_escape_html_attr): new function. (escape_html_attr_finish): new function. (rb_escape_html_attr): use them to quote the converted result. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19173 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 7 +++++ enc/trans/escape.trans | 66 +++++++++++++++++++++++++++++++++++------ test/ruby/test_econv.rb | 20 +++++++++++-- 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index e343da4221..54cdac37dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Sat Sep 6 12:19:36 2008 Tanaka Akira + + * enc/trans/escape.trans (escape_html_attr_init): new function. + (fun_so_escape_html_attr): new function. + (escape_html_attr_finish): new function. + (rb_escape_html_attr): use them to quote the converted result. + Sat Sep 6 07:54:36 2008 Tadayoshi Funaba * complex.c: uses f_real_p macro. diff --git a/enc/trans/escape.trans b/enc/trans/escape.trans index d1612187aa..544e1ace4a 100644 --- a/enc/trans/escape.trans +++ b/enc/trans/escape.trans @@ -53,11 +53,7 @@ fun_so_escape_html_chref(void *statep, const unsigned char *s, size_t l, unsigne transcode_generate_node(ActionMap.parse(map_html_text), "escape_html_text") map_html_attr = {} - map_html_attr["{00-21,23-25,27-3B,3D,3F-FF}"] = :nomap - map_html_attr["22"] = :func_so - map_html_attr["26"] = :func_so - map_html_attr["3C"] = :func_so - map_html_attr["3E"] = :func_so + map_html_attr["{00-FF}"] = :func_so transcode_generate_node(ActionMap.parse(map_html_attr), "escape_html_attr") %> @@ -87,16 +83,68 @@ rb_escape_html_text = { NULL, NULL, NULL, &fun_so_escape_html_chref }; +#define END 0 +#define NORMAL 1 + +static int +escape_html_attr_init(void *statep) +{ + unsigned char *sp = statep; + *sp = END; + return 0; +} + +static VALUE +fun_so_escape_html_attr(void *statep, const unsigned char *s, size_t l, unsigned char *o) +{ + unsigned char *sp = statep; + int n = 0; + if (*sp == END) { + *sp = NORMAL; + o[n++] = '"'; + } + switch (s[0]) { + case '&': + case '<': + case '>': + case '"': + n += fun_so_escape_html_chref(statep, s, l, o+n); + break; + + default: + o[n++] = s[0]; + break; + } + return n; +} + +static int +escape_html_attr_finish(void *statep, unsigned char *o) +{ + unsigned char *sp = statep; + int n = 0; + + if (*sp == END) { + o[n++] = '"'; + } + + o[n++] = '"'; + *sp = END; + + return n; +} + static const rb_transcoder rb_escape_html_attr = { "", "html-attr-escaped", escape_html_attr, TRANSCODE_TABLE_INFO, 1, /* input_unit_length */ 1, /* max_input */ - 6, /* max_output */ - stateless_converter, /* stateful_type */ - 0, NULL, NULL, - NULL, NULL, NULL, &fun_so_escape_html_chref + 7, /* max_output */ + stateful_encoder, /* stateful_type */ + 1, escape_html_attr_init, escape_html_attr_init, + NULL, NULL, NULL, fun_so_escape_html_attr, + escape_html_attr_finish }; void diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb index c458371ad4..49ba2ae9d3 100644 --- a/test/ruby/test_econv.rb +++ b/test/ruby/test_econv.rb @@ -727,14 +727,30 @@ class TestEncodingConverter < Test::Unit::TestCase assert_equal("&", ec.convert("&")) end - def test_html_escape + def test_html_escape_text ec = Encoding::Converter.new("", "amp-escaped") assert_equal('&<>"', ec.convert("&<>\"")) + assert_equal('', ec.finish) ec = Encoding::Converter.new("", "html-text-escaped") assert_equal('&<>"', ec.convert("&<>\"")) + assert_equal('', ec.finish) + end + + def test_html_escape_attr + ec = Encoding::Converter.new("", "html-attr-escaped") + assert_equal('""', ec.finish) ec = Encoding::Converter.new("", "html-attr-escaped") - assert_equal('&<>"', ec.convert("&<>\"")) + assert_equal('', ec.convert("")) + assert_equal('""', ec.finish) + + ec = Encoding::Converter.new("", "html-attr-escaped") + assert_equal('""', ec.convert('"')) + assert_equal('"', ec.finish) + + ec = Encoding::Converter.new("", "html-attr-escaped") + assert_equal('"&<>"', ec.convert("&<>\"")) + assert_equal('"', ec.finish) end end