From fb7854fbccfa241071c6fbe2f6b4167c58c52ce3 Mon Sep 17 00:00:00 2001 From: Jocelyn Fiat Date: Mon, 24 Oct 2011 17:23:36 +0200 Subject: [PATCH] Added visitor patterns to WSF_VALUE Handling UTF-8 unencoding for WSF_VALUE ... Added WSF_TABLE_VALUE to handle list[]=a&list[]=b ... Library encoder: added UTF8 facilities --- examples/restbucks/client/README.txt | 11 ++ library/server/ewsgi/src/support/ewf_header.e | 11 ++ .../value/visitor/wsf_value_agent_iterator.e | 68 +++++++++ .../value/visitor/wsf_value_iterator.e | 51 +++++++ .../value/visitor/wsf_value_null_visitor.e | 38 +++++ .../request/value/visitor/wsf_value_visitor.e | 48 +++++++ .../request/value/wsf_multiple_string_value.e | 9 +- .../wsf/src/request/value/wsf_string_value.e | 14 +- .../wsf/src/request/value/wsf_table_value.e | 131 ++++++++++++++++++ library/server/wsf/src/request/wsf_value.e | 22 ++- library/server/wsf/src/wsf_request.e | 122 +++++++++++++--- .../wsf/tests/{ => src}/test_wsf_request.e | 0 library/server/wsf/tests/src/test_wsf_value.e | 23 +++ library/server/wsf/tests/tests-safe.ecf | 2 +- library/server/wsf/tests/tests.ecf | 2 +- library/text/encoder/encoder-safe.ecf | 11 +- library/text/encoder/encoder.ecf | 1 + library/text/encoder/src/base64.e | 5 +- library/text/encoder/src/encoder.e | 6 +- library/text/encoder/src/html_encoder.e | 8 +- library/text/encoder/src/url_encoder.e | 9 +- library/text/encoder/src/utf8_encoder.e | 70 ++++++++++ library/text/encoder/src/utf8_url_encoder.e | 94 +++++++++++++ library/text/encoder/src/xml_encoder.e | 8 +- library/text/encoder/tests/test_url_encoder.e | 18 ++- .../text/encoder/tests/test_utf8_encoder.e | 51 +++++++ ...{text_xml_encoder.e => test_xml_encoder.e} | 0 27 files changed, 781 insertions(+), 52 deletions(-) create mode 100644 examples/restbucks/client/README.txt create mode 100644 library/server/wsf/src/request/value/visitor/wsf_value_agent_iterator.e create mode 100644 library/server/wsf/src/request/value/visitor/wsf_value_iterator.e create mode 100644 library/server/wsf/src/request/value/visitor/wsf_value_null_visitor.e create mode 100644 library/server/wsf/src/request/value/visitor/wsf_value_visitor.e create mode 100644 library/server/wsf/src/request/value/wsf_table_value.e rename library/server/wsf/tests/{ => src}/test_wsf_request.e (100%) create mode 100644 library/server/wsf/tests/src/test_wsf_value.e create mode 100644 library/text/encoder/src/utf8_encoder.e create mode 100644 library/text/encoder/src/utf8_url_encoder.e create mode 100644 library/text/encoder/tests/test_utf8_encoder.e rename library/text/encoder/tests/{text_xml_encoder.e => test_xml_encoder.e} (100%) diff --git a/examples/restbucks/client/README.txt b/examples/restbucks/client/README.txt new file mode 100644 index 00000000..033eaaf4 --- /dev/null +++ b/examples/restbucks/client/README.txt @@ -0,0 +1,11 @@ +Make sure to have the Clib generated in the related cURL library + +- if you use EiffelStudio >= 7.0 + check %ISE_LIBRARY%\library\cURL\spec\%ISE_C_COMPILER%\$ISE_PLATFORM + or $ISE_LIBRARY/library/cURL/spec/$ISE_PLATFORM + +- otherwise if you use earlier version + check under ext/ise_library/curl/spec/... + +And on Windows, be sure to get the libcurl.dll from %ISE_LIBRARY%\studio\spec\%ISE_PLATFORM%\bin\libcurl.dll + diff --git a/library/server/ewsgi/src/support/ewf_header.e b/library/server/ewsgi/src/support/ewf_header.e index 618f9af3..b2bc0bbb 100644 --- a/library/server/ewsgi/src/support/ewf_header.e +++ b/library/server/ewsgi/src/support/ewf_header.e @@ -144,6 +144,17 @@ feature -- Content related header add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t) end + put_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8) + do + put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; charset=" + c + "") + end + + add_content_type_with_charset (t: READABLE_STRING_8; c: READABLE_STRING_8) + -- same as `put_content_type_with_charset', but allow multiple definition of "Content-Type" + do + add_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; charset=" + c + "") + end + put_content_type_with_name (t: READABLE_STRING_8; n: READABLE_STRING_8) do put_header_key_value ({HTTP_HEADER_NAMES}.header_content_type, t + "; name=%"" + n + "%"") diff --git a/library/server/wsf/src/request/value/visitor/wsf_value_agent_iterator.e b/library/server/wsf/src/request/value/visitor/wsf_value_agent_iterator.e new file mode 100644 index 00000000..e647f08d --- /dev/null +++ b/library/server/wsf/src/request/value/visitor/wsf_value_agent_iterator.e @@ -0,0 +1,68 @@ +note + description: "[ + Iterator visitor on WSF_VALUE using agent for callback + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_VALUE_AGENT_ITERATOR + +inherit + WSF_VALUE_ITERATOR + redefine + process_table, + process_multiple_string, + process_string + end + +create + make + +feature {NONE} -- Initialization + + make + do + create on_table_actions + create on_string_actions + create on_multiple_string_actions + end + +feature -- Actions + + on_table_actions: ACTION_SEQUENCE [TUPLE [WSF_TABLE_VALUE]] + + on_string_actions: ACTION_SEQUENCE [TUPLE [WSF_STRING_VALUE]] + + on_multiple_string_actions: ACTION_SEQUENCE [TUPLE [WSF_MULTIPLE_STRING_VALUE]] + +feature -- Visitor + + process_table (v: WSF_TABLE_VALUE) + do + on_table_actions.call ([v]) + process_iterable_of_value (v) + end + + process_string (v: WSF_STRING_VALUE) + do + on_string_actions.call ([v]) + end + + process_multiple_string (v: WSF_MULTIPLE_STRING_VALUE) + do + on_multiple_string_actions.call ([v]) + process_iterable_of_value (v) + end + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/value/visitor/wsf_value_iterator.e b/library/server/wsf/src/request/value/visitor/wsf_value_iterator.e new file mode 100644 index 00000000..f0970a1e --- /dev/null +++ b/library/server/wsf/src/request/value/visitor/wsf_value_iterator.e @@ -0,0 +1,51 @@ +note + description: "[ + Iterator visitor on WSF_VALUE + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_VALUE_ITERATOR + +inherit + WSF_VALUE_VISITOR + +feature -- Helper + + process_iterable_of_value (it: ITERABLE [WSF_VALUE]) + do + across + it as c + loop + c.item.process (Current) + end + end + +feature -- Visitor + + process_table (v: WSF_TABLE_VALUE) + do + process_iterable_of_value (v) + end + + process_string (v: WSF_STRING_VALUE) + do + end + + process_multiple_string (v: WSF_MULTIPLE_STRING_VALUE) + do + process_iterable_of_value (v) + end + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/value/visitor/wsf_value_null_visitor.e b/library/server/wsf/src/request/value/visitor/wsf_value_null_visitor.e new file mode 100644 index 00000000..0ff11115 --- /dev/null +++ b/library/server/wsf/src/request/value/visitor/wsf_value_null_visitor.e @@ -0,0 +1,38 @@ +note + description: "[ + NULL Visitor implementation + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_VALUE_NULL_VISITOR + +inherit + WSF_VALUE_VISITOR + +feature -- Visitor + + process_table (v: WSF_TABLE_VALUE) + do + end + + process_string (v: WSF_STRING_VALUE) + do + end + + process_multiple_string (v: WSF_MULTIPLE_STRING_VALUE) + do + end + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e b/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e new file mode 100644 index 00000000..d57c1cde --- /dev/null +++ b/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e @@ -0,0 +1,48 @@ +note + description: "[ + Component to visit WSF_VALUE + ]" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_VALUE_VISITOR + +feature -- Visitor + + safe_process_value (v: detachable WSF_TABLE_VALUE) + do + if v /= Void then + v.process (Current) + end + end + + process_table (v: WSF_TABLE_VALUE) + require + v_attached: v /= Void + deferred + end + + process_string (v: WSF_STRING_VALUE) + require + v_attached: v /= Void + deferred + end + + process_multiple_string (v: WSF_MULTIPLE_STRING_VALUE) + require + v_attached: v /= Void + deferred + end + +;note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/src/request/value/wsf_multiple_string_value.e b/library/server/wsf/src/request/value/wsf_multiple_string_value.e index 1325e67e..beb3334b 100644 --- a/library/server/wsf/src/request/value/wsf_multiple_string_value.e +++ b/library/server/wsf/src/request/value/wsf_multiple_string_value.e @@ -127,10 +127,17 @@ feature -- Element change string_values.extend (s) end +feature -- Visitor + + process (vis: WSF_VALUE_VISITOR) + do + vis.process_multiple_string (Current) + end + invariant string_values_not_empty: string_values.count >= 1 -;note +note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ diff --git a/library/server/wsf/src/request/value/wsf_string_value.e b/library/server/wsf/src/request/value/wsf_string_value.e index dfc7e4a6..af7b482e 100644 --- a/library/server/wsf/src/request/value/wsf_string_value.e +++ b/library/server/wsf/src/request/value/wsf_string_value.e @@ -65,20 +65,14 @@ feature -- Conversion create Result.make_from_string (string) end -feature {NONE} -- Implementation +feature -- Visitor - url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32 - -- Decoded url-encoded string `s' + process (vis: WSF_VALUE_VISITOR) do - Result := url_encoder.decoded_string (s) + vis.process_string (Current) end - url_encoder: URL_ENCODER - once - create Result - end - -;note +note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ diff --git a/library/server/wsf/src/request/value/wsf_table_value.e b/library/server/wsf/src/request/value/wsf_table_value.e new file mode 100644 index 00000000..ff601e4f --- /dev/null +++ b/library/server/wsf/src/request/value/wsf_table_value.e @@ -0,0 +1,131 @@ +note + description: "[ + Table value which can contain value indexed by a key + ]" + date: "$Date$" + revision: "$Revision$" + +class + WSF_TABLE_VALUE + +inherit + WSF_VALUE + + ITERABLE [WSF_VALUE] + +create + make + +feature {NONE} -- Initialization + + make (a_name: READABLE_STRING_8) + do + name := url_decoded_string (a_name) + create values.make (5) + end + +feature -- Access + + name: READABLE_STRING_32 + + first_value: detachable WSF_VALUE + -- First value if any. + do + across + values as c + until + Result /= Void + loop + Result := c.item + end + end + + first_key: detachable READABLE_STRING_32 + do + across + values as c + until + Result /= Void + loop + Result := c.key + end + end + + values: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + + value (k: READABLE_STRING_32): detachable WSF_VALUE + do + Result := values.item (k) + end + + count: INTEGER + do + Result := values.count + end + +feature -- Element change + + add_value (a_value: WSF_VALUE; k: READABLE_STRING_32) + require + same_name: a_value.name.same_string (name) + do + values.force (a_value, k) + end + +feature -- Traversing + + new_cursor: ITERATION_CURSOR [WSF_VALUE] + do + Result := values.new_cursor + end + +feature -- Helper + + same_string (a_other: READABLE_STRING_GENERAL): BOOLEAN + -- Does `a_other' represent the same string as `Current'? + do + if values.count = 1 and then attached first_value as f then + Result := f.same_string (a_other) + end + end + + is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN + -- Does `a_other' represent the same case insensitive string as `Current'? + do + if values.count = 1 and then attached first_value as f then + Result := f.is_case_insensitive_equal (a_other) + end + end + + as_string: STRING_32 + do + create Result.make_from_string ("{") + if values.count = 1 and then attached first_key as fk then + Result.append (fk + ": ") + if attached value (fk) as fv then + Result.append (fv.as_string) + else + Result.append ("???") + end + else + across + values as c + loop + if Result.count > 1 then + Result.append_character (',') + end + Result.append (c.key + ": ") + Result.append (c.item.as_string) + end + end + Result.append_character ('}') + end + +feature -- Visitor + + process (vis: WSF_VALUE_VISITOR) + do + vis.process_table (Current) + end + +end diff --git a/library/server/wsf/src/request/wsf_value.e b/library/server/wsf/src/request/wsf_value.e index b0bc9b35..b7c84ff6 100644 --- a/library/server/wsf/src/request/wsf_value.e +++ b/library/server/wsf/src/request/wsf_value.e @@ -1,6 +1,5 @@ note description: "Summary description for {WSF_VALUE}." - author: "" date: "$Date$" revision: "$Revision$" @@ -28,7 +27,7 @@ feature -- Helper end is_case_insensitive_equal (a_other: READABLE_STRING_8): BOOLEAN - -- Does `a_other' represent the same case insensitive string as `Current'? + -- Does `a_other' represent the same case insensitive string as `Current'? deferred end @@ -46,6 +45,25 @@ feature -- Query deferred end +feature {NONE} -- Implementation + + url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32 + -- Decoded url-encoded string `s' + do + Result := url_encoder.decoded_string (s) + end + + url_encoder: URL_ENCODER + once + create {UTF8_URL_ENCODER} Result --| Chrome is UTF-8 encoding the non ascii in query + end + +feature -- Visitor + + process (vis: WSF_VALUE_VISITOR) + deferred + end + note copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index 79f29d75..8b4add05 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -133,7 +133,7 @@ feature {NONE} -- Access: global variable end across - form_data_parameters as vars + form_parameters as vars loop Result.force (vars.item, vars.item.name) end @@ -163,7 +163,7 @@ feature -- Access: global variable if v = Void then v := query_parameter (a_name) if v = Void then - v := form_data_parameter (a_name) + v := form_parameter (a_name) if v = Void then v := cookie (a_name) end @@ -866,13 +866,83 @@ feature {NONE} -- Query parameters: implementation end end - add_value_to_table (a_name: READABLE_STRING_32; a_value: READABLE_STRING_32; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) + add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) local - v: WSF_VALUE + + v: detachable WSF_VALUE + n,k,r: STRING_8 + k32: STRING_32 + p,q: INTEGER + tb,ptb: detachable WSF_TABLE_VALUE do - v := new_string_value (a_name, a_value) + --| Check if this is a list format such as choice[] or choice[a] or even choice[a][] or choice[a][b][c]... + p := a_name.index_of ('[', 1) + if p > 0 then + q := a_name.index_of (']', p + 1) + if q > p then + n := a_name.substring (1, p - 1) + r := a_name.substring (q + 1, a_name.count) + r.left_adjust; r.right_adjust + + create tb.make (n) + if a_table.has_key (tb.name) and then attached {WSF_TABLE_VALUE} a_table.found_item as l_existing_table then + tb := l_existing_table + end + + k := a_name.substring (p + 1, q - 1) + k.left_adjust; k.right_adjust + if k.is_empty then + k.append_integer (tb.count) + end + v := tb + n.append_character ('[') + n.append (k) + n.append_character (']') + + from + until + r.is_empty + loop + ptb := tb + p := r.index_of ({CHARACTER_8} '[', 1) + if p > 0 then + q := r.index_of ({CHARACTER_8} ']', p + 1) + if q > p then + k32 := url_encoder.decoded_string (k) + if attached {WSF_TABLE_VALUE} ptb.value (k32) as l_tb_value then + tb := l_tb_value + else + create tb.make (n) + ptb.add_value (tb, k32) + end + + k := r.substring (p + 1, q - 1) + r := r.substring (q + 1, r.count) + r.left_adjust; r.right_adjust + if k.is_empty then + k.append_integer (tb.count) + end + n.append_character ('[') + n.append (k) + n.append_character (']') + end + else + r.wipe_out + --| Ignore bad value + end + end + tb.add_value (new_string_value (n, a_value), k) + else + --| Missing end bracket + end + end + if v = Void then + v := new_string_value (a_name, a_value) + end if a_table.has_key (v.name) and then attached a_table.found_item as l_existing_value then - if attached {WSF_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then + if tb /= Void then + --| Already done in previous part + elseif attached {WSF_MULTIPLE_STRING_VALUE} l_existing_value as l_multi then l_multi.add_value (v) else a_table.force (create {WSF_MULTIPLE_STRING_VALUE}.make_with_array (<>), v.name) @@ -883,17 +953,29 @@ feature {NONE} -- Query parameters: implementation end end -feature -- Form fields and related +feature -- Form fields and related - form_data_parameters: ITERABLE [WSF_VALUE] + form_data_parameters: like form_parameters + obsolete "[2011-oct-24] Use form_parameters" do - Result := form_data_parameters_table + Result := form_parameters end - form_data_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE + form_data_parameter (a_name: READABLE_STRING_8): like form_parameter + obsolete "[2011-oct-24] Use form_parameter (a_name:...)" + do + Result := form_parameter (a_name) + end + + form_parameters: ITERABLE [WSF_VALUE] + do + Result := form_parameters_table + end + + form_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE -- Field for name `a_name'. do - Result := form_data_parameters_table.item (a_name) + Result := form_parameters_table.item (a_name) end uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, STRING] @@ -907,7 +989,7 @@ feature -- Form fields and related feature {NONE} -- Form fields and related - form_data_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + form_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] -- Variables sent by POST request local vars: like internal_form_data_parameters_table @@ -1156,7 +1238,7 @@ feature {NONE} -- Temporary File handling feature {NONE} -- Implementation: Form analyzer - analyze_multipart_form (t: STRING; s: STRING; vars: like form_data_parameters_table) + analyze_multipart_form (t: STRING; s: STRING; vars: like form_parameters_table) -- Analyze multipart form content --| FIXME[2011-06-21]: integrate eMIME parser library require @@ -1222,16 +1304,16 @@ feature {NONE} -- Implementation: Form analyzer end end - analyze_multipart_form_input (s: STRING; vars_post: like form_data_parameters_table) + analyze_multipart_form_input (s: STRING; vars_post: like form_parameters_table) -- Analyze multipart entry require s_not_empty: s /= Void and then not s.is_empty local n, i,p, b,e: INTEGER - l_name, l_filename, l_content_type: detachable STRING - l_header: detachable STRING - l_content: detachable STRING - l_line: detachable STRING + l_name, l_filename, l_content_type: detachable STRING_8 + l_header: detachable STRING_8 + l_content: detachable STRING_8 + l_line: detachable STRING_8 l_up_file_info: WGI_UPLOADED_FILE_DATA do from @@ -1372,7 +1454,7 @@ feature {NONE} -- Internal value internal_query_parameters_table: detachable like query_parameters_table -- cached value for `query_parameters' - internal_form_data_parameters_table: detachable like form_data_parameters_table + internal_form_data_parameters_table: detachable like form_parameters_table -- cached value for `form_fields' internal_cookies_table: detachable like cookies_table @@ -1487,7 +1569,7 @@ feature {NONE} -- Implementation: utilities url_encoder: URL_ENCODER once - create Result + create {UTF8_URL_ENCODER} Result end date_time_utilities: HTTP_DATE_TIME_UTILITIES diff --git a/library/server/wsf/tests/test_wsf_request.e b/library/server/wsf/tests/src/test_wsf_request.e similarity index 100% rename from library/server/wsf/tests/test_wsf_request.e rename to library/server/wsf/tests/src/test_wsf_request.e diff --git a/library/server/wsf/tests/src/test_wsf_value.e b/library/server/wsf/tests/src/test_wsf_value.e new file mode 100644 index 00000000..79c553f0 --- /dev/null +++ b/library/server/wsf/tests/src/test_wsf_value.e @@ -0,0 +1,23 @@ +note + description: "Summary description for {TEST_WSF_VALUE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + TEST_WSF_VALUE + +inherit + EQA_TEST_SET + +feature {NONE} -- Events + + test_table + local + tb: WSF_TABLE_VALUE + do + create tb.make ("table") + assert ("Ok", True) + end + +end diff --git a/library/server/wsf/tests/tests-safe.ecf b/library/server/wsf/tests/tests-safe.ecf index bf9302f3..02b06917 100644 --- a/library/server/wsf/tests/tests-safe.ecf +++ b/library/server/wsf/tests/tests-safe.ecf @@ -16,6 +16,6 @@ - + diff --git a/library/server/wsf/tests/tests.ecf b/library/server/wsf/tests/tests.ecf index 553a52f7..0343e227 100644 --- a/library/server/wsf/tests/tests.ecf +++ b/library/server/wsf/tests/tests.ecf @@ -16,6 +16,6 @@ - + diff --git a/library/text/encoder/encoder-safe.ecf b/library/text/encoder/encoder-safe.ecf index 24ceb5c2..1b249ddf 100644 --- a/library/text/encoder/encoder-safe.ecf +++ b/library/text/encoder/encoder-safe.ecf @@ -1,5 +1,5 @@ - + @@ -7,18 +7,18 @@ /EIFGENs$ /.svn$ - + /tests$ - - + /.git$ @@ -29,7 +29,6 @@ - + - diff --git a/library/text/encoder/encoder.ecf b/library/text/encoder/encoder.ecf index 5ba35276..de457982 100644 --- a/library/text/encoder/encoder.ecf +++ b/library/text/encoder/encoder.ecf @@ -11,6 +11,7 @@ + /tests$ diff --git a/library/text/encoder/src/base64.e b/library/text/encoder/src/base64.e index 821139de..b72e3c31 100644 --- a/library/text/encoder/src/base64.e +++ b/library/text/encoder/src/base64.e @@ -16,7 +16,10 @@ inherit feature -- Access - name: STRING = "base64" + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("base64") + end feature -- Status report diff --git a/library/text/encoder/src/encoder.e b/library/text/encoder/src/encoder.e index daec5d7b..78e05379 100644 --- a/library/text/encoder/src/encoder.e +++ b/library/text/encoder/src/encoder.e @@ -5,12 +5,12 @@ note date: "$Date$" revision: "$Revision$" -deferred class +deferred class ENCODER [U -> READABLE_STRING_GENERAL, E -> READABLE_STRING_GENERAL] --| U:unencoded type, E:encoded type feature -- Access - name: STRING + name: READABLE_STRING_8 -- Encoding name. deferred end @@ -61,7 +61,7 @@ feature -- Decoder end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/text/encoder/src/html_encoder.e b/library/text/encoder/src/html_encoder.e index d3a409aa..efd76425 100644 --- a/library/text/encoder/src/html_encoder.e +++ b/library/text/encoder/src/html_encoder.e @@ -22,7 +22,10 @@ inherit feature -- Access - name: STRING = "HTML-encoded" + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("HTML-encoded") + end feature -- Status report @@ -71,6 +74,7 @@ feature -- Decoder c: CHARACTER cl_i: CELL [INTEGER] do + has_error := False n := v.count create Result.make (n) create cl_i.put (0) @@ -255,7 +259,7 @@ feature {NONE} -- Implementation: decoder end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/text/encoder/src/url_encoder.e b/library/text/encoder/src/url_encoder.e index 26a0c832..386b64da 100644 --- a/library/text/encoder/src/url_encoder.e +++ b/library/text/encoder/src/url_encoder.e @@ -22,7 +22,10 @@ inherit feature -- Access - name: STRING = "URL-encoded" + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("URL-encoded") + end feature -- Status report @@ -138,7 +141,9 @@ feature -- Decoder c: CHARACTER pr: CELL [INTEGER] s32: STRING_32 + changed: BOOLEAN do + has_error := False n := v.count create s32.make (n) Result := s32 @@ -148,12 +153,14 @@ feature -- Decoder c := v.item (i) inspect c when '+' then + changed := True s32.append_character ({CHARACTER_32}' ') when '%%' then -- An escaped character ? if i = n then s32.append_character (c.to_character_32) else + changed := True create pr.put (i) s32.append (url_decoded_char (v, pr)) i := pr.item diff --git a/library/text/encoder/src/utf8_encoder.e b/library/text/encoder/src/utf8_encoder.e new file mode 100644 index 00000000..71a818e5 --- /dev/null +++ b/library/text/encoder/src/utf8_encoder.e @@ -0,0 +1,70 @@ +note + description: "[ + Summary description for {UTF8_ENCODER}. + + see: http://en.wikipedia.org/wiki/UTF-8 + ]" + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + UTF8_ENCODER + +inherit + ENCODER [STRING_32, STRING_8] + + UNICODE_CONVERSION + export + {NONE} all + {ANY} is_valid_utf8 + undefine + is_little_endian + end + + PLATFORM + export + {NONE} all + end + +feature -- Access + + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("UTF8-encoded") + end + +feature -- Status report + + has_error: BOOLEAN + +feature -- Encoder + + encoded_string (s: STRING_32): STRING_8 + -- UTF8-encoded value of `s'. + do + Result := utf32_to_utf8 (s) + has_error := not last_conversion_successful + end + +feature -- Decoder + + decoded_string (v: STRING_8): STRING_32 + -- The UTF8-encoded equivalent of the given string + do + Result := utf8_to_utf32 (v) + has_error := not last_conversion_successful + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/text/encoder/src/utf8_url_encoder.e b/library/text/encoder/src/utf8_url_encoder.e new file mode 100644 index 00000000..f1fbffdd --- /dev/null +++ b/library/text/encoder/src/utf8_url_encoder.e @@ -0,0 +1,94 @@ +note + description: "[ + Summary description for {URL_ENCODER}. + + See: http://www.faqs.org/rfcs/rfc3986.html + ]" + legal: "See notice at end of class." + status: "See notice at end of class." + date: "$Date$" + revision: "$Revision$" + +class + UTF8_URL_ENCODER + +inherit + URL_ENCODER + redefine + default_create, + name, + encoded_string, partial_encoded_string, + decoded_string + end + + UNICODE_CONVERSION + export + {NONE} all + {ANY} is_valid_utf8 + undefine + is_little_endian + redefine + default_create + end + +feature {NONE} -- Initialization + + default_create + do + Precursor {UNICODE_CONVERSION} + end + +feature -- Access + + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("UTF8-URL-encoded") + end + +feature -- Encoder + + encoded_string (s: READABLE_STRING_32): READABLE_STRING_8 + -- URL-encoded value of `s'. + do + Result := Precursor (s) + if not has_error then + Result := utf32_to_utf8 (Result) + has_error := not last_conversion_successful + end + end + + partial_encoded_string (s: READABLE_STRING_32; a_ignore: ARRAY [CHARACTER]): READABLE_STRING_8 + -- URL-encoded value of `s'. + do + Result := Precursor (s, a_ignore) + if not has_error then + Result := utf32_to_utf8 (Result) + has_error := not last_conversion_successful + end + end + +feature -- Decoder + + decoded_string (v: READABLE_STRING_8): READABLE_STRING_32 + -- The URL-encoded equivalent of the given string + do + Result := Precursor (v) + if not has_error then + if is_valid_utf8 (Result) then + Result := utf8_to_utf32 (Result) + has_error := not last_conversion_successful + end + end + end + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/text/encoder/src/xml_encoder.e b/library/text/encoder/src/xml_encoder.e index 23273037..4fd33f94 100644 --- a/library/text/encoder/src/xml_encoder.e +++ b/library/text/encoder/src/xml_encoder.e @@ -22,7 +22,10 @@ inherit feature -- Access - name: STRING = "XML-encoded" + name: READABLE_STRING_8 + do + create {IMMUTABLE_STRING_8} Result.make_from_string ("XML-encoded") + end feature -- Status report @@ -71,6 +74,7 @@ feature -- Decoder c: CHARACTER cl_i: CELL [INTEGER] do + has_error := False n := v.count create Result.make (n) create cl_i.put (0) @@ -255,7 +259,7 @@ feature {NONE} -- Implementation: decoder end note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/text/encoder/tests/test_url_encoder.e b/library/text/encoder/tests/test_url_encoder.e index 40a7e16d..e55fe18f 100644 --- a/library/text/encoder/tests/test_url_encoder.e +++ b/library/text/encoder/tests/test_url_encoder.e @@ -20,6 +20,9 @@ feature -- Test routines testing: "url-encoded" do test_url_encoded_encoding ("http://domain.tld/foo/bar/script.php?test='toto'&foo=bar&title=il était une fois") + test_url_encoded_encoding ("été") + test_url_encoded_decoding ("%%E9t%%E9", "été") + test_url_encoded_decoding ("%%C3%%A9t%%C3%%A9", "été") end test_url_encoded_encoding (s: STRING_32) @@ -31,11 +34,22 @@ feature -- Test routines create b e := b.encoded_string (s) u := b.decoded_string (e) - assert ("decoded encoded string is same", u ~ s) + assert ("decoded encoded string is same for string %"" + u + "%"", u ~ s) end + test_url_encoded_decoding (s: STRING_8; e: STRING_32) + local + u: STRING_32 + b: URL_ENCODER + do + create b + u := b.decoded_string (s) + assert ("decoded encoded string is same for %"" + s + "%"", u ~ e) + end + + note - copyright: "Copyright (c) 1984-2011, Eiffel Software and others" + copyright: "2011-2011, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/text/encoder/tests/test_utf8_encoder.e b/library/text/encoder/tests/test_utf8_encoder.e new file mode 100644 index 00000000..f87bdac1 --- /dev/null +++ b/library/text/encoder/tests/test_utf8_encoder.e @@ -0,0 +1,51 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date$" + revision: "$Revision$" + testing: "type/manual" + +class + TEST_UTF8_ENCODER + +inherit + EQA_TEST_SET + +feature -- Test routines + + test_url_encoded_encoder + note + testing: "url-encoded" + do +-- test_utf8_decoding ("summer=été&weird=ŕ", "summer=été&weird=ŕ") + test_utf8_decoding ("%%C3%%A9t%%C3%%A9", "été") + end + + test_utf8_decoding (s: STRING_8; e: STRING_32) + local + url: URL_ENCODER + u: STRING_32 + b: UTF8_ENCODER + do + create b + create url + u := b.decoded_string (url.decoded_string (s)) + assert ("decoded encoded string is same for %"" + s + "%"", u ~ e) + end + + +note + copyright: "2011-2011, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end + + diff --git a/library/text/encoder/tests/text_xml_encoder.e b/library/text/encoder/tests/test_xml_encoder.e similarity index 100% rename from library/text/encoder/tests/text_xml_encoder.e rename to library/text/encoder/tests/test_xml_encoder.e