diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e index e28c1151..8bbf1b25 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_handler.e @@ -70,6 +70,7 @@ feature -- Request processing e: EXECUTION_ENVIRONMENT enc: URL_ENCODER + utf: UTF_CONVERTER do l_request_uri := a_handler.uri l_headers_map := a_handler.request_header_map @@ -80,13 +81,13 @@ feature -- Request processing across vars as c loop - env.force (enc.encoded_string (c.item), enc.encoded_string (c.key)) + env.force (utf.utf_32_string_to_utf_8_string_8 (c.item), utf.utf_32_string_to_utf_8_string_8 (c.key)) end else create env.make (0) end - --| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env' + --| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env' from l_headers_map.start until diff --git a/library/server/ewsgi/src/implementation/wgi_request_from_table.e b/library/server/ewsgi/src/implementation/wgi_request_from_table.e index 69d20e1a..5274075a 100644 --- a/library/server/ewsgi/src/implementation/wgi_request_from_table.e +++ b/library/server/ewsgi/src/implementation/wgi_request_from_table.e @@ -253,7 +253,7 @@ feature -- Access: HTTP_* CGI meta parameters - 1.1 do Result := meta_string_variable ({WGI_META_NAMES}.http_if_match) end - + http_if_modified_since: detachable READABLE_STRING_8 -- Modification check on resource do @@ -306,8 +306,11 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO s: like meta_string_variable table: STRING_TABLE [READABLE_STRING_8] l_query_string: like query_string - l_request_uri: detachable STRING_32 + l_request_uri: detachable READABLE_STRING_8 + s8: STRING_8 l_empty_string: like empty_string + enc: PERCENT_ENCODER + utf: UTF_CONVERTER do create {STRING_8} l_empty_string.make_empty empty_string := l_empty_string @@ -319,8 +322,11 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO until a_vars.after loop - -- Warning: truncated value to ascii !!! - table.force (a_vars.item_for_iteration.to_string_8, a_vars.key_for_iteration) + if attached {READABLE_STRING_32} a_vars.item_for_iteration as s32 then + table.force (utf.utf_32_string_to_utf_8_string_8 (s32), a_vars.key_for_iteration) + else + table.force (a_vars.item_for_iteration.to_string_8, a_vars.key_for_iteration) + end a_vars.forth end @@ -370,14 +376,22 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO if s /= Void then l_request_uri := s else - --| It might occur that REQUEST_URI is not available, so let's compute it from SCRIPT_NAME - create l_request_uri.make_from_string (script_name) + --| REQUEST_URI is not always available, in this case, + --| compute it from SCRIPT_NAME, PATH_INFO and QUERY_STRING which are required by CGI. + create s8.make_from_string (script_name) + create enc + enc.append_partial_percent_encoded_string_to (utf.utf_8_string_8_to_string_32 (path_info), s8, <<'/', '!', '$', '&', '%'', '(', ')', '*', '+', ',', ';', '='>>) if not l_query_string.is_empty then - l_request_uri.append_character ('?') - l_request_uri.append (l_query_string) + s8.append_character ('?') + s8.append (l_query_string) end + l_request_uri := s8 end - request_uri := single_slash_starting_string (l_request_uri) + --| FIXME: should it strip "////abc/def" to "/abc/def" ? + --| Not sure why this was done before. +-- l_request_uri := single_slash_starting_string (l_request_uri) + request_uri := l_request_uri + set_meta_string_variable ({WGI_META_NAMES}.request_uri, l_request_uri) end set_orig_path_info (s: READABLE_STRING_8) @@ -482,7 +496,7 @@ invariant empty_string_unchanged: empty_string.is_empty note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software diff --git a/library/server/wsf/src/request/value/wsf_string.e b/library/server/wsf/src/request/value/wsf_string.e index 0da28891..a969072e 100644 --- a/library/server/wsf/src/request/value/wsf_string.e +++ b/library/server/wsf/src/request/value/wsf_string.e @@ -25,11 +25,8 @@ feature {NONE} -- Initialization make (a_name: READABLE_STRING_8; a_string: READABLE_STRING_8) do - name := url_decoded_string (a_name) - value := url_decoded_string (a_string) - - url_encoded_name := a_name - url_encoded_value := a_string + url_encoded_name := utf_8_percent_encoded_string (a_name) + url_encoded_value := utf_8_percent_encoded_string (a_string) end feature -- Access @@ -38,11 +35,31 @@ feature -- Access -- --| Note that the value might be html encoded as well --| this is the application responsibility to html decode it + local + v: like internal_name + do + v := internal_name + if v = Void then + v := url_decoded_string (url_encoded_name) + internal_name := v + end + Result := v + end value: READABLE_STRING_32 -- --| Note that the value might be html encoded as well --| this is the application responsibility to html decode it + local + v: like internal_value + do + v := internal_value + if v = Void then + v := url_decoded_string (url_encoded_value) + internal_value := v + end + Result := v + end url_encoded_name: READABLE_STRING_8 -- URL encoded string of `name'. @@ -50,6 +67,14 @@ feature -- Access url_encoded_value: READABLE_STRING_8 -- URL encoded string of `value'. +feature {NONE} -- Access: internals + + internal_name: detachable like name + -- Cached value of `name'. + + internal_value: detachable like value + -- Cached value of `value'. + feature -- Conversion integer_value: INTEGER @@ -81,7 +106,7 @@ feature -- Element change change_name (a_name: like name) do - name := url_decoded_string (a_name) + internal_name := Void url_encoded_name := a_name ensure then a_name.same_string (url_encoded_name) @@ -122,8 +147,89 @@ feature -- Visitor vis.process_string (Current) end +feature {NONE} -- Implementation + + utf_8_percent_encoded_string (s: READABLE_STRING_8): READABLE_STRING_8 + -- Percent-encode the UTF-8 sequence characters from UTF-8 encoded `s' and + -- return the Result. + local + s8: STRING_8 + i, n, nb: INTEGER + do + -- First check if there are such UTF-8 character + -- If it has, convert them and return a new object as Result + -- otherwise return `s' directly to avoid creating a new object + from + i := 1 + n := s.count + nb := 0 + until + i > n + loop + if s.code (i) > 0x7F then -- >= 128 + nb := nb + 1 + end + i := i + 1 + end + if nb > 0 then + create s8.make (s.count + nb * 3) + utf_8_string_8_into_percent_encoded_string_8 (s, s8) + Result := s8 + else + Result := s + end + end + + utf_8_string_8_into_percent_encoded_string_8 (s: READABLE_STRING_8; a_result: STRING_8) + -- Copy STRING_32 corresponding to UTF-8 sequence `s' appended into `a_result'. + local + i: INTEGER + n: INTEGER + c: NATURAL_32 + do + from + n := s.count + a_result.grow (a_result.count + n) + until + i >= n + loop + i := i + 1 + c := s.code (i) + if c <= 0x7F then + -- 0xxxxxxx + a_result.append_code (c) + elseif c <= 0xDF then + -- 110xxxxx 10xxxxxx + url_encoder.append_percent_encoded_character_code_to (c, a_result) + i := i + 1 + if i <= n then + url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) + end + elseif c <= 0xEF then + -- 1110xxxx 10xxxxxx 10xxxxxx + url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) + i := i + 2 + if i <= n then + url_encoder.append_percent_encoded_character_code_to (s.code (i - 1), a_result) + url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) + end + elseif c <= 0xF7 then + -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) + i := i + 3 + if i <= n then + url_encoder.append_percent_encoded_character_code_to (s.code (i - 2), a_result) + url_encoder.append_percent_encoded_character_code_to (s.code (i - 1), a_result) + url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) + end + else + a_result.append_code (c) + end + end + end + note - copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" + copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software