Fixed various unicode issue related to query and form parameters.

Especially for the multipart/form-data encoding.
Factorized code related to smart parameters computing (handling list , table, ...) in WSF_VALUE_UTILITIES.
Fixed an issue with percent_encoded_path_info computation from request_uri.
Fixed issue with cookie addition having same cookie name.
This commit is contained in:
2015-11-05 00:35:12 +01:00
parent dde6a0b7de
commit 941281e3ed
13 changed files with 455 additions and 349 deletions

View File

@@ -42,6 +42,9 @@ feature -- Settings
is_verbose: BOOLEAN is_verbose: BOOLEAN
-- Has verbose output (default: True)? -- Has verbose output (default: True)?
unicode_output_enabled: BOOLEAN
-- Display names and values as unicode.
feature -- Settings change feature -- Settings change
set_is_verbose (b: BOOLEAN) set_is_verbose (b: BOOLEAN)
@@ -50,6 +53,12 @@ feature -- Settings change
is_verbose := b is_verbose := b
end end
set_unicode_output_enabled (b: BOOLEAN)
-- if `b' then enable unicode output, otherwise disable.
do
unicode_output_enabled := b
end
feature -- Execution feature -- Execution
append_connector_informations_to (req: WSF_REQUEST; res: WSF_RESPONSE; a_output: STRING) append_connector_informations_to (req: WSF_REQUEST; res: WSF_RESPONSE; a_output: STRING)
@@ -232,7 +241,7 @@ feature {NONE} -- Implementation
it as c it as c
loop loop
s.append (" - ") s.append (" - ")
s.append (utf.escaped_utf_32_string_to_utf_8_string_8 (c.key)) append_unicode (c.key, s)
s.append_character (' ') s.append_character (' ')
if attached c.item as l_item then if attached c.item as l_item then
s.append_character ('{') s.append_character ('{')
@@ -302,7 +311,11 @@ feature {NONE} -- Implementation
it as c it as c
loop loop
a_output.append (" - ") a_output.append (" - ")
a_output.append (c.item.url_encoded_name) if unicode_output_enabled then
append_unicode (c.item.name, a_output)
else
a_output.append (c.item.url_encoded_name)
end
t := c.item.generating_type t := c.item.generating_type
if t.same_string ("WSF_STRING") then if t.same_string ("WSF_STRING") then
else else
@@ -313,15 +326,15 @@ feature {NONE} -- Implementation
end end
a_output.append_character ('=') a_output.append_character ('=')
if attached {WSF_STRING} c.item as l_str then if attached {WSF_STRING} c.item as l_str then
s := l_str.url_encoded_value if unicode_output_enabled then
s := l_str.value
else
s := l_str.url_encoded_value
end
else else
s := c.item.string_representation s := c.item.string_representation
end end
if s.is_valid_as_string_8 then v := utf.utf_32_string_to_utf_8_string_8 (s)
v := s.as_string_8
else
v := utf.escaped_utf_32_string_to_utf_8_string_8 (s)
end
if v.has ('%N') then if v.has ('%N') then
a_output.append (eol) a_output.append (eol)
across across
@@ -349,7 +362,6 @@ feature {NONE} -- Implementation
local local
n: INTEGER n: INTEGER
v: READABLE_STRING_8 v: READABLE_STRING_8
utf: UTF_CONVERTER
do do
if is_verbose then if is_verbose then
a_output.append (a_title) a_output.append (a_title)
@@ -368,11 +380,7 @@ feature {NONE} -- Implementation
it as c it as c
loop loop
a_output.append (" - ") a_output.append (" - ")
if c.key.is_valid_as_string_8 then append_unicode (c.key, a_output)
a_output.append (c.key.as_string_8)
else
a_output.append (utf.utf_32_string_to_utf_8_string_8 (c.key))
end
a_output.append_character ('=') a_output.append_character ('=')
v := c.item v := c.item
if v.has ('%N') then if v.has ('%N') then
@@ -398,6 +406,17 @@ feature {NONE} -- Implementation
end end
end end
append_unicode (s: READABLE_STRING_GENERAL; a_output: STRING)
local
utf: UTF_CONVERTER
do
--if s.is_valid_as_string_8 then
--a_output.append (s.as_string_8)
--else
a_output.append (utf.utf_32_string_to_utf_8_string_8 (s))
--end
end
feature -- Constants feature -- Constants
eol: STRING = "%N" eol: STRING = "%N"

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER}." description: "Summary description for {WSF_APPLICATION_X_WWW_FORM_URLENCODED_HANDLER}."
author: ""
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -12,6 +11,11 @@ inherit
WSF_MIME_HANDLER_HELPER WSF_MIME_HANDLER_HELPER
WSF_VALUE_UTILITIES
export
{NONE} all
end
feature -- Status report feature -- Status report
valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN valid_content_type (a_content_type: HTTP_CONTENT_TYPE): BOOLEAN
@@ -54,7 +58,7 @@ feature -- Execution
if j > 0 then if j > 0 then
l_name := s.substring (1, j - 1) l_name := s.substring (1, j - 1)
l_value := s.substring (j + 1, s.count) l_value := s.substring (j + 1, s.count)
add_string_value_to_table (l_name, l_value, a_vars) add_percent_encoded_string_value_to_table (l_name, l_value, a_vars)
end end
end end
end end
@@ -62,7 +66,7 @@ feature -- Execution
end end
note note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -1,6 +1,5 @@
note note
description: "Summary description for {WSF_MULTIPART_FORM_DATA_HANDLER}." description: "Summary description for {WSF_MULTIPART_FORM_DATA_HANDLER}."
author: ""
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
@@ -240,7 +239,7 @@ feature {NONE} -- Implementation: Form analyzer
--| `l_up_file' might have a new name --| `l_up_file' might have a new name
req.save_uploaded_file (l_up_file, l_content) req.save_uploaded_file (l_up_file, l_content)
else else
add_string_value_to_table (l_name, l_content, vars) add_utf_8_string_value_to_table (l_name, l_content, vars)
end end
else else
req.error_handler.add_custom_error (0, "unamed multipart entry", Void) req.error_handler.add_custom_error (0, "unamed multipart entry", Void)
@@ -254,7 +253,7 @@ feature {NONE} -- Implementation: Form analyzer
-- Default content type -- Default content type
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -34,10 +34,10 @@ feature -- Access
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- <Precursor>
do do
name := url_decoded_string (a_name) name := a_name
ensure then url_encoded_name := url_encoded_string (a_name)
a_name.same_string (url_encoded_name)
end end
feature -- Status report feature -- Status report
@@ -71,7 +71,7 @@ feature -- Visitor
end end
note note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -89,10 +89,9 @@ feature -- Access
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- <Precursor>
do do
name := a_name name := a_name
ensure then
a_name.same_string (name)
end end
feature -- Status report feature -- Status report
@@ -180,7 +179,7 @@ invariant
string_values_not_empty: values.count >= 1 string_values_not_empty: values.count >= 1
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -16,17 +16,24 @@ inherit
end end
create create
make make,
make_with_percent_encoded_values
convert convert
string_representation: {READABLE_STRING_32, STRING_32} string_representation: {READABLE_STRING_32, STRING_32}
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_name: READABLE_STRING_8; a_string: READABLE_STRING_8) make (a_name: READABLE_STRING_GENERAL; a_string: READABLE_STRING_GENERAL)
do do
url_encoded_name := utf_8_percent_encoded_string (a_name) url_encoded_name := url_encoded_string (a_name)
url_encoded_value := utf_8_percent_encoded_string (a_string) url_encoded_value := url_encoded_string (a_string)
end
make_with_percent_encoded_values (a_encoded_name: READABLE_STRING_8; a_encoded_value: READABLE_STRING_8)
do
url_encoded_name := a_encoded_name
url_encoded_value := a_encoded_value
end end
feature -- Access feature -- Access
@@ -105,11 +112,10 @@ feature -- Status report
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- <Precursor>
do do
internal_name := Void internal_name := a_name
url_encoded_name := a_name url_encoded_name := url_encoded_string (a_name)
ensure then
a_name.same_string (url_encoded_name)
end end
feature -- Helper feature -- Helper
@@ -147,89 +153,163 @@ feature -- Visitor
vis.process_string (Current) vis.process_string (Current)
end end
feature {NONE} -- Implementation --feature {NONE} -- Implementation
utf_8_percent_encoded_string (s: READABLE_STRING_8): READABLE_STRING_8 -- utf_8_percent_encoded_string (s: READABLE_STRING_GENERAL): READABLE_STRING_8
-- Percent-encode the UTF-8 sequence characters from UTF-8 encoded `s' and -- -- Percent-encode the UTF-8 sequence characters from UTF-8 encoded `s' and
-- return the Result. -- -- return the Result.
local -- local
s8: STRING_8 -- s8: STRING_8
i, n, nb: INTEGER -- i, n, nb: INTEGER
do -- do
-- First check if there are such UTF-8 character -- -- First check if there are such UTF-8 character
-- If it has, convert them and return a new object as Result -- -- If it has, convert them and return a new object as Result
-- otherwise return `s' directly to avoid creating a new object -- -- otherwise return `s' directly to avoid creating a new object
from -- from
i := 1 -- i := 1
n := s.count -- n := s.count
nb := 0 -- nb := 0
until -- until
i > n -- i > n
loop -- loop
if s.code (i) > 0x7F then -- >= 128 -- if s.code (i) > 0x7F then -- >= 128
nb := nb + 1 -- nb := nb + 1
end -- end
i := i + 1 -- i := i + 1
end -- end
if nb > 0 then -- if nb > 0 then
create s8.make (s.count + nb * 3) -- create s8.make (s.count + nb * 3)
utf_8_string_8_into_percent_encoded_string_8 (s, s8) -- utf_8_string_into_percent_encoded_string_8 (s, s8)
Result := s8 -- Result := s8
else -- else
Result := s -- Result := s.to_string_8
end -- end
end -- end
utf_8_string_8_into_percent_encoded_string_8 (s: READABLE_STRING_8; a_result: STRING_8) -- utf_8_string_into_percent_encoded_string_8 (s: READABLE_STRING_GENERAL; a_result: STRING_8)
-- Copy STRING_32 corresponding to UTF-8 sequence `s' appended into `a_result'. -- -- Copy STRING_32 corresponding to UTF-8 sequence `s' appended into `a_result'.
local -- local
i: INTEGER -- i: INTEGER
n: INTEGER -- n: INTEGER
c: NATURAL_32 -- c: NATURAL_32
do -- do
from -- from
n := s.count -- n := s.count
a_result.grow (a_result.count + n) -- a_result.grow (a_result.count + n)
until -- until
i >= n -- i >= n
loop -- loop
i := i + 1 -- i := i + 1
c := s.code (i) -- c := s.code (i)
if c <= 0x7F then -- if c <= 0x7F then
-- 0xxxxxxx -- -- 0xxxxxxx
a_result.append_code (c) -- a_result.append_code (c)
elseif c <= 0xDF then -- elseif c <= 0xDF then
-- 110xxxxx 10xxxxxx -- -- 110xxxxx 10xxxxxx
url_encoder.append_percent_encoded_character_code_to (c, a_result) -- url_encoder.append_percent_encoded_character_code_to (c, a_result)
i := i + 1 -- i := i + 1
if i <= n then -- if i <= n then
url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) -- url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result)
end -- end
elseif c <= 0xEF then -- elseif c <= 0xEF then
-- 1110xxxx 10xxxxxx 10xxxxxx -- -- 1110xxxx 10xxxxxx 10xxxxxx
url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) -- url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result)
i := i + 2 -- i := i + 2
if i <= n then -- 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 - 1), a_result)
url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) -- url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result)
end -- end
elseif c <= 0xF7 then -- elseif c <= 0xF7 then
-- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx -- -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) -- url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result)
i := i + 3 -- i := i + 3
if i <= n then -- 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 - 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 - 1), a_result)
url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result) -- url_encoder.append_percent_encoded_character_code_to (s.code (i), a_result)
end -- end
else -- else
a_result.append_code (c) -- -- FIXME: unicode character, first utf8 it, then percent encode it.
end -- append_percent_encoded_unicode_character_code_to (c, a_result)
end ---- a_result.append_code (c)
end -- end
-- end
-- end
-- append_percent_encoded_ascii_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
-- -- Append extended ascii character code `a_code' as percent-encoded content into `a_result'
-- -- Note: it does not UTF-8 convert this extended ASCII.
-- require
-- is_extended_ascii: a_code <= 0xFF
-- local
-- c: INTEGER
-- do
-- if a_code > 0xFF then
-- -- Unicode
-- append_percent_encoded_unicode_character_code_to (a_code, a_result)
-- else
-- -- Extended ASCII
-- c := a_code.to_integer_32
-- a_result.append_code (37) -- 37 '%%'
-- a_result.append_code (hex_digit [c |>> 4])
-- a_result.append_code (hex_digit [c & 0xF])
-- end
-- ensure
-- appended: a_result.count > old a_result.count
-- end
-- append_percent_encoded_unicode_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
-- -- Append Unicode character code `a_code' as UTF-8 and percent-encoded content into `a_result'
-- -- Note: it does include UTF-8 conversion of extended ASCII and Unicode.
-- do
-- if a_code <= 0x7F then
-- -- 0xxxxxxx
-- append_percent_encoded_ascii_character_code_to (a_code, a_result)
-- elseif a_code <= 0x7FF then
-- -- 110xxxxx 10xxxxxx
-- append_percent_encoded_ascii_character_code_to ((a_code |>> 6) | 0xC0, a_result)
-- append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
-- elseif a_code <= 0xFFFF then
-- -- 1110xxxx 10xxxxxx 10xxxxxx
-- append_percent_encoded_ascii_character_code_to ((a_code |>> 12) | 0xE0, a_result)
-- append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
-- append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
-- else
-- -- c <= 1FFFFF - there are no higher code points
-- -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-- append_percent_encoded_ascii_character_code_to ((a_code |>> 18) | 0xF0, a_result)
-- append_percent_encoded_ascii_character_code_to (((a_code |>> 12) & 0x3F) | 0x80, a_result)
-- append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
-- append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
-- end
-- ensure
-- appended: a_result.count > old a_result.count
-- end
-- hex_digit: SPECIAL [NATURAL_32]
-- -- Hexadecimal digits.
-- once
-- create Result.make_filled (0, 16)
-- Result [0] := {NATURAL_32} 48 -- 48 '0'
-- Result [1] := {NATURAL_32} 49 -- 49 '1'
-- Result [2] := {NATURAL_32} 50 -- 50 '2'
-- Result [3] := {NATURAL_32} 51 -- 51 '3'
-- Result [4] := {NATURAL_32} 52 -- 52 '4'
-- Result [5] := {NATURAL_32} 53 -- 53 '5'
-- Result [6] := {NATURAL_32} 54 -- 54 '6'
-- Result [7] := {NATURAL_32} 55 -- 55 '7'
-- Result [8] := {NATURAL_32} 56 -- 56 '8'
-- Result [9] := {NATURAL_32} 57 -- 57 '9'
-- Result [10] := {NATURAL_32} 65 -- 65 'A'
-- Result [11] := {NATURAL_32} 66 -- 66 'B'
-- Result [12] := {NATURAL_32} 67 -- 67 'C'
-- Result [13] := {NATURAL_32} 68 -- 68 'D'
-- Result [14] := {NATURAL_32} 69 -- 69 'E'
-- Result [15] := {NATURAL_32} 70 -- 70 'F'
-- end
note note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -17,23 +17,34 @@ inherit
ITERABLE [WSF_VALUE] ITERABLE [WSF_VALUE]
create create
make make,
make_with_percent_encoded_name
feature {NONE} -- Initialization feature {NONE} -- Initialization
make (a_name: READABLE_STRING_8) make (a_name: READABLE_STRING_GENERAL)
do do
name := url_decoded_string (a_name) name := a_name.as_string_32
url_encoded_name := a_name url_encoded_name := url_encoded_string (a_name)
create values.make (5) create values.make (3)
end
make_with_percent_encoded_name (a_encoded_name: READABLE_STRING_8)
do
url_encoded_name := a_encoded_name
name := url_decoded_string (a_encoded_name)
create values.make (3)
end end
feature -- Access feature -- Access
name: READABLE_STRING_32 name: READABLE_STRING_32
-- Parameter name -- <Precursor>
--| Note that the value might be html encoded as well
--| this is the application responsibility to html decode it
url_encoded_name: READABLE_STRING_8 url_encoded_name: READABLE_STRING_8
-- URL encoded string of `name'.
first_value: detachable WSF_VALUE first_value: detachable WSF_VALUE
-- First value if any. -- First value if any.
@@ -59,13 +70,16 @@ feature -- Access
end end
values: HASH_TABLE [WSF_VALUE, STRING_32] values: HASH_TABLE [WSF_VALUE, STRING_32]
-- Associated items values, indexed by unicode name.
value (k: READABLE_STRING_GENERAL): detachable WSF_VALUE value (k: READABLE_STRING_GENERAL): detachable WSF_VALUE
-- Value associated with name `k'.
do do
Result := values.item (k.to_string_32) Result := values.item (k.to_string_32)
end end
count: INTEGER count: INTEGER
-- Number of values.
do do
Result := values.count Result := values.count
end end
@@ -77,14 +91,15 @@ feature -- Access
Result := first_name Result := first_name
end end
feature -- Element change
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- <Precursor>
do do
name := url_decoded_string (a_name) name := a_name
url_encoded_name := a_name url_encoded_name := url_encoded_string (a_name)
ensure then
a_name.same_string (url_encoded_name)
end end
feature -- Status report feature -- Status report
@@ -217,7 +232,7 @@ feature -- Visitor
end end
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -65,11 +65,10 @@ feature -- Status report
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- <Precursor>
do do
name := url_decoded_string (a_name) name := a_name
url_encoded_name := a_name url_encoded_name := url_encoded_string (a_name)
ensure then
a_name.same_string (url_encoded_name)
end end
feature -- Status report feature -- Status report
@@ -182,7 +181,7 @@ feature -- Basic operation
if f.exists then if f.exists then
f.rename_file (a_destination) f.rename_file (a_destination)
Result := True Result := True
end end
end end
ensure ensure
removed: not exists removed: not exists
@@ -241,7 +240,7 @@ feature -- Element change
end end
note note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -36,8 +36,10 @@ feature -- Access
feature -- Element change feature -- Element change
change_name (a_name: like name) change_name (a_name: like name)
-- Change parameter name -- Change parameter `name'.
deferred deferred
ensure
name_changed: a_name.same_string (name)
end end
feature -- Status report feature -- Status report
@@ -128,7 +130,7 @@ feature -- Visitor
end end
note note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -7,122 +7,25 @@ note
deferred class deferred class
WSF_MIME_HANDLER_HELPER WSF_MIME_HANDLER_HELPER
inherit
ANY
WSF_VALUE_UTILITIES
export
{NONE} all
end
feature {NONE} -- Implementation feature {NONE} -- Implementation
full_input_data (req: WSF_REQUEST): STRING_8 full_input_data (req: WSF_REQUEST): STRING_8
-- Read or reused full input data from `req'.
do do
create Result.make (0) create Result.make (0)
req.read_input_data_into (Result) req.read_input_data_into (Result)
end end
add_string_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
do
add_value_to_table (a_name, new_string_value (a_name, a_value), a_table)
end
add_value_to_table (a_name: READABLE_STRING_8; a_value: WSF_VALUE; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
local
l_decoded_name: STRING_32
v: detachable WSF_VALUE
n,k,r: STRING_32
-- k32: STRING_32
p,q: INTEGER
tb,ptb: detachable WSF_TABLE
do
--| Check if this is a list format such as choice[] or choice[a] or even choice[a][] or choice[a][b][c]...
l_decoded_name := url_encoder.decoded_string (a_name)
p := l_decoded_name.index_of ({CHARACTER_32}'[', 1)
if p > 0 then
q := l_decoded_name.index_of ({CHARACTER_32}']', p + 1)
if q > p then
n := l_decoded_name.substring (1, p - 1)
r := l_decoded_name.substring (q + 1, l_decoded_name.count)
r.left_adjust; r.right_adjust
create tb.make (n)
if a_table.has_key (tb.name) and then attached {WSF_TABLE} a_table.found_item as l_existing_table then
tb := l_existing_table
end
k := l_decoded_name.substring (p + 1, q - 1)
k.left_adjust; k.right_adjust
if k.is_empty then
k.append_integer (tb.count + 1)
end
v := tb
n.append_character ({CHARACTER_32}'[')
n.append (k)
n.append_character ({CHARACTER_32}']')
from
until
r.is_empty
loop
ptb := tb
p := r.index_of ({CHARACTER_32} '[', 1)
if p > 0 then
q := r.index_of ({CHARACTER_32} ']', p + 1)
if q > p then
if attached {WSF_TABLE} ptb.value (k) as l_tb_value then
tb := l_tb_value
else
create tb.make (n)
ptb.add_value (tb, k)
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 + 1)
end
n.append_character ('[')
n.append (k)
n.append_character (']')
end
else
r.wipe_out
--| Ignore bad value
end
end
a_value.change_name (n)
tb.add_value (a_value, k)
else
--| Missing end bracket
end
end
if v = Void then
a_value.change_name (a_name)
v := a_value
end
if a_table.has_key (v.name) and then attached a_table.found_item as l_existing_value then
if tb /= Void then
--| Already done in previous part
elseif attached {WSF_MULTIPLE_STRING} l_existing_value as l_multi then
l_multi.add_value (v)
else
a_table.force (create {WSF_MULTIPLE_STRING}.make_with_array (<<l_existing_value, v>>), v.name)
check replaced: a_table.found and then a_table.found_item ~ l_existing_value end
end
else
a_table.force (v, v.name)
end
end
new_string_value (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8): WSF_STRING
do
create Result.make (a_name, a_value)
end
feature {NONE} -- Implementation
url_encoder: URL_ENCODER
once
create {UTF8_URL_ENCODER} Result
end
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2015, 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)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software

View File

@@ -0,0 +1,158 @@
note
description: "[
Utility routines to handle parameters and convert them as string, list or table values.
]"
date: "$Date$"
revision: "$Revision$"
class
WSF_VALUE_UTILITIES
inherit
ANY
SHARED_WSF_PERCENT_ENCODER
rename
percent_encoder as url_encoder
export
{NONE} all
end
feature -- Smart parameter identification
add_utf_8_string_value_to_table (a_utf_8_name: READABLE_STRING_8; a_utf_8_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
local
utf: UTF_CONVERTER
n,v: READABLE_STRING_32
do
n := utf.utf_8_string_8_to_string_32 (a_utf_8_name)
v := utf.utf_8_string_8_to_string_32 (a_utf_8_value)
add_value_to_table (n, new_string_value (n, v), a_table)
end
add_percent_encoded_string_value_to_table (a_encoded_name: READABLE_STRING_8; a_encoded_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
local
v: WSF_STRING
do
v := new_string_value_with_percent_encoded_values (a_encoded_name, a_encoded_value)
add_value_to_table (v.name, v, a_table)
end
add_value_to_table (a_name: READABLE_STRING_GENERAL; a_value: WSF_VALUE; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
local
l_decoded_name: STRING_32
l_encoded_name: READABLE_STRING_8
v: detachable WSF_VALUE
n,k,r,vn: STRING_32
p,q: INTEGER
tb,ptb: detachable WSF_TABLE
do
--| Check if this is a list format such as choice[] or choice[a] or even choice[a][] or choice[a][b][c]...
l_decoded_name := a_name.as_string_32 --url_encoder.decoded_string (a_name)
l_encoded_name := url_encoder.percent_encoded_string (l_decoded_name)
p := l_decoded_name.index_of ({CHARACTER_32}'[', 1)
n := l_decoded_name
if p > 0 then
q := l_decoded_name.index_of ({CHARACTER_32}']', p + 1)
if q > p then
n := l_decoded_name.substring (1, p - 1)
r := l_decoded_name.substring (q + 1, l_decoded_name.count)
r.left_adjust; r.right_adjust
create tb.make (n)
if attached {WSF_TABLE} a_table.item (tb.name) as l_existing_table then
tb := l_existing_table
end
k := l_decoded_name.substring (p + 1, q - 1)
k.left_adjust; k.right_adjust
if k.is_empty then
k.append_integer (tb.count + 1)
end
v := tb
create vn.make_from_string (n)
vn.append_character ({CHARACTER_32}'[')
vn.append (k)
vn.append_character ({CHARACTER_32}']')
from
until
r.is_empty
loop
ptb := tb
p := r.index_of ({CHARACTER_32} '[', 1)
if p > 0 then
q := r.index_of ({CHARACTER_32} ']', p + 1)
if q > p then
if attached {WSF_TABLE} ptb.value (k) as l_tb_value then
tb := l_tb_value
else
create tb.make (n)
ptb.add_value (tb, k)
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 + 1)
end
vn.append_character ('[')
vn.append (k)
vn.append_character (']')
end
else
r.wipe_out
--| Ignore bad value
end
end
a_value.change_name (vn)
tb.add_value (a_value, k)
else
--| Missing end bracket
end
end
if v = Void then
a_value.change_name (l_decoded_name)
v := a_value
end
if attached a_table.item (n) as l_existing_value then
if tb /= Void then
--| Already done in previous part
elseif attached {WSF_MULTIPLE_STRING} l_existing_value as l_multi then
l_multi.add_value (v)
elseif attached {WSF_TABLE} l_existing_value as l_table then
-- Keep previous values (most likely we have table[1]=foo, table[2]=bar ..and table=/foo/bar
-- Anyway for this case, we keep the previous version, and ignore this "conflict"
else
a_table.force (create {WSF_MULTIPLE_STRING}.make_with_array (<<l_existing_value, v>>), v.name)
check replaced: a_table.found and then a_table.found_item ~ l_existing_value end
end
else
a_table.force (v, n)
end
end
feature -- Factory
new_string_value (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_GENERAL): WSF_STRING
do
create Result.make (a_name, a_value)
end
new_string_value_with_percent_encoded_values (a_encoded_name: READABLE_STRING_8; a_encoded_value: READABLE_STRING_8): WSF_STRING
do
create Result.make_with_percent_encoded_values (a_encoded_name, a_encoded_value)
end
note
copyright: "2011-2015, 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
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

View File

@@ -20,8 +20,8 @@ note
About https support: `is_https' indicates if the request is made through an https connection or not. About https support: `is_https' indicates if the request is made through an https connection or not.
]" ]"
date: "$Date: 2014-05-14 16:52:42 +0200 (mer., 14 mai 2014) $" date: "$Date$"
revision: "$Revision: 95057 $" revision: "$Revision$"
class class
WSF_REQUEST WSF_REQUEST
@@ -41,6 +41,11 @@ inherit
{NONE} all {NONE} all
end end
WSF_VALUE_UTILITIES
export
{NONE} all
end
create {WSF_EXECUTION, WGI_EXPORTER} create {WSF_EXECUTION, WGI_EXPORTER}
make_from_wgi make_from_wgi
@@ -846,7 +851,7 @@ feature -- Access: CGI meta parameters - 1.1
local local
l_result: like internal_percent_encoded_path_info l_result: like internal_percent_encoded_path_info
r: READABLE_STRING_8 r: READABLE_STRING_8
i: INTEGER i,m,n,spos: INTEGER
do do
l_result := internal_percent_encoded_path_info l_result := internal_percent_encoded_path_info
if l_result = Void then if l_result = Void then
@@ -860,6 +865,28 @@ feature -- Access: CGI meta parameters - 1.1
if attached script_name as s then if attached script_name as s then
if l_result.starts_with (s) then if l_result.starts_with (s) then
l_result := l_result.substring (s.count + 1, l_result.count) l_result := l_result.substring (s.count + 1, l_result.count)
else
--| Handle Rewrite url engine, to have clean path
from
i := 1
m := l_result.count
n := s.count
until
i > m or i > n or l_result[i] /= s[i]
loop
if l_result[i] = '/' then
spos := i
end
i := i + 1
end
if i > 1 then
if l_result[i-1] = '/' then
i := i -1
elseif spos > 0 then
i := spos
end
l_result := l_result.substring (i, m)
end
end end
end end
internal_percent_encoded_path_info := l_result internal_percent_encoded_path_info := l_result
@@ -1399,7 +1426,7 @@ feature {NONE} -- Cookies
k.left_adjust k.left_adjust
k.right_adjust k.right_adjust
if not k.is_empty then if not k.is_empty then
add_value_to_table (k, v, l_cookies) add_percent_encoded_string_value_to_table (k, v, l_cookies)
end end
end end
end end
@@ -1463,7 +1490,7 @@ feature {WSF_REQUEST_PATH_PARAMETERS_SOURCE} -- Path parameters: Element change
across across
lst as c lst as c
loop loop
add_value_to_table (c.key, c.item, l_table) add_percent_encoded_string_value_to_table (c.key, c.item, l_table)
end end
src.update_path_parameters (l_table) src.update_path_parameters (l_table)
end end
@@ -1494,7 +1521,7 @@ feature {NONE} -- Query parameters: implementation
vars: like internal_query_parameters_table vars: like internal_query_parameters_table
p,e: INTEGER p,e: INTEGER
rq_uri: like request_uri rq_uri: like request_uri
s: detachable STRING s: detachable READABLE_STRING_8
do do
vars := internal_query_parameters_table vars := internal_query_parameters_table
if vars = Void then if vars = Void then
@@ -1556,7 +1583,7 @@ feature {NONE} -- Query parameters: implementation
l_name := s l_name := s
l_value := empty_string_8 l_value := empty_string_8
end end
add_value_to_table (l_name, l_value, Result) add_percent_encoded_string_value_to_table (l_name, l_value, Result)
end end
end end
end end
@@ -1715,100 +1742,6 @@ feature {NONE} -- Form fields and related
Result := vars Result := vars
end end
feature {NONE} -- Implementation: smart parameter identification
add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: STRING_TABLE [WSF_VALUE])
-- Add urlencoded parameter `a_name'=`a_value' to `a_table'
-- following smart computation such as handling the "..[..]" as table
local
v: detachable WSF_VALUE
n, k, r: STRING_8
k32: STRING_32
p, q: INTEGER
tb, ptb: detachable WSF_TABLE
do
--| 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} 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 + 1)
end
v := tb
create n.make_from_string (n)
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_decoded_string (k)
if attached {WSF_TABLE} 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 + 1)
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 tb /= Void then
--| Already done in previous part
elseif attached {WSF_MULTIPLE_STRING} l_existing_value as l_multi then
l_multi.add_value (v)
elseif attached {WSF_TABLE} l_existing_value as l_table then
-- Keep previous values (most likely we have table[1]=foo, table[2]=bar ..and table=/foo/bar
-- Anyway for this case, we keep the previous version, and ignore this "conflict"
else
a_table.force (create {WSF_MULTIPLE_STRING}.make_with_array (<<l_existing_value, v>>), v.name)
check replaced: a_table.found and then a_table.found_item ~ l_existing_value end
end
else
a_table.force (v, v.name)
end
end
feature -- Uploaded File Handling feature -- Uploaded File Handling
is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN
@@ -2133,11 +2066,6 @@ feature {NONE} -- Implementation: utilities
one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/') one_starting_slash: Result[1] = '/' and (Result.count = 1 or else Result[2] /= '/')
end end
new_string_value (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8): WSF_STRING
do
create Result.make (a_name, a_value)
end
empty_string_32: IMMUTABLE_STRING_32 empty_string_32: IMMUTABLE_STRING_32
-- Reusable empty string -- Reusable empty string
once once

View File

@@ -319,7 +319,7 @@ feature -- Header output operation: helpers
feature -- Header add cookie feature -- Header add cookie
add_cookie (a_cookie: WSF_COOKIE) add_cookie (a_cookie: WSF_COOKIE)
-- Add a Set-Cookie header field to the response, -- Add a Set-Cookie header field to the response,
-- if no Set-Cookie header field already use same cookie-name. -- if no Set-Cookie header field already use same cookie-name.
--| Servers SHOULD NOT include more than one Set-Cookie header field in --| Servers SHOULD NOT include more than one Set-Cookie header field in
--| the same response with the same cookie-name. --| the same response with the same cookie-name.
@@ -328,7 +328,7 @@ feature -- Header add cookie
do do
across across
internal_header.headers as ic internal_header.headers as ic
until until
l_same_cookie_name l_same_cookie_name
loop loop
if ic.item.starts_with ("Set-Cookie:") then if ic.item.starts_with ("Set-Cookie:") then
@@ -564,7 +564,7 @@ feature {NONE} -- Implemenation
loop loop
j := j + 1 j := j + 1
end end
if j > n then if j <= n then
Result := a_cookie_name.same_characters (a_cookie_line, j, i, 1) Result := a_cookie_name.same_characters (a_cookie_line, j, i, 1)
end end
end end