diff --git a/library/server/wsf/router/uri/wsf_uri_handler_context.e b/library/server/wsf/router/uri/wsf_uri_handler_context.e index a6b6f7f4..dfd880ca 100644 --- a/library/server/wsf/router/uri/wsf_uri_handler_context.e +++ b/library/server/wsf/router/uri/wsf_uri_handler_context.e @@ -40,7 +40,7 @@ feature -- Request data feature -- Item - item (a_name: READABLE_STRING_32): detachable WSF_VALUE + item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Variable value for parameter or variable `a_name' -- See `{WSF_REQUEST}.item(s)' do diff --git a/library/server/wsf/router/uri_template/wsf_uri_template_handler_context.e b/library/server/wsf/router/uri_template/wsf_uri_template_handler_context.e index 7a2bac7a..7e9ad4f5 100644 --- a/library/server/wsf/router/uri_template/wsf_uri_template_handler_context.e +++ b/library/server/wsf/router/uri_template/wsf_uri_template_handler_context.e @@ -24,6 +24,8 @@ inherit item end + WSF_REQUEST_PATH_PARAMETERS_SOURCE + create make @@ -45,30 +47,40 @@ feature -- Access feature -- Environment - old_path_parameters: detachable ITERABLE [WSF_VALUE] + path_parameters_count: INTEGER + do + Result := uri_template_match.path_variables.count + end + + urlencoded_path_parameters: TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8] + -- + do + Result := uri_template_match.path_variables + end + + previous_path_parameters_source: detachable WSF_REQUEST_PATH_PARAMETERS_SOURCE apply (req: WSF_REQUEST) -- do - old_path_parameters := req.path_parameters - req.import_raw_path_parameters (uri_template_match.path_variables) + previous_path_parameters_source := req.path_parameters_source + req.set_path_parameters_source (Current) end revert (req: WSF_REQUEST) -- do - if attached old_path_parameters as vals then - req.reset_path_parameters (vals) - end + req.set_path_parameters_source (previous_path_parameters_source) + previous_path_parameters_source := Void end feature -- Item - item (a_name: READABLE_STRING_32): detachable WSF_VALUE + item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Variable value for parameter or variable `a_name' -- See `{WSF_REQUEST}.item(s)' do - Result := path_parameter (a_name.as_string_8) --| Should we handle url-encoded name? + Result := path_parameter (a_name) --| Should we handle url-encoded name? if Result = Void then Result := request.item (a_name) end @@ -76,20 +88,23 @@ feature -- Item feature -- Path parameter - path_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE + path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + local + n: READABLE_STRING_8 do - if attached uri_template_match.url_decoded_path_variable (a_name) as s then - create {WSF_STRING} Result.make (a_name, s) + n := uri_template_match.encoded_name (a_name) + if attached uri_template_match.path_variable (n) as s then + create {WSF_STRING} Result.make (n, s) end end - is_integer_path_parameter (a_name: READABLE_STRING_8): BOOLEAN + is_integer_path_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN -- Is path parameter related to `a_name' an integer value? do Result := attached string_path_parameter (a_name) as s and then s.is_integer end - integer_path_parameter (a_name: READABLE_STRING_8): INTEGER + integer_path_parameter (a_name: READABLE_STRING_GENERAL): INTEGER -- Integer value for path parameter `a_name' if relevant. require is_integer_path_parameter: is_integer_path_parameter (a_name) @@ -97,13 +112,13 @@ feature -- Path parameter Result := integer_from (path_parameter (a_name)) end - string_path_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + string_path_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- String value for path parameter `a_name' if relevant. do Result := string_from (path_parameter (a_name)) end - string_array_path_parameter (a_name: READABLE_STRING_8): detachable ARRAY [READABLE_STRING_32] + string_array_path_parameter (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32] -- Array of string values for path parameter `a_name' if relevant. do Result := string_array_for (a_name, agent string_path_parameter) diff --git a/library/server/wsf/router/wsf_handler_context.e b/library/server/wsf/router/wsf_handler_context.e index c9ea5236..c1c974f4 100644 --- a/library/server/wsf/router/wsf_handler_context.e +++ b/library/server/wsf/router/wsf_handler_context.e @@ -19,6 +19,8 @@ inherit {NONE} all end + DEBUG_OUTPUT + feature -- Access request: WSF_REQUEST @@ -125,7 +127,7 @@ feature -- Query feature -- Item - item (a_name: READABLE_STRING_32): detachable WSF_VALUE + item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Variable value for parameter or variable `a_name' -- See `{WSF_REQUEST}.item(s)' deferred @@ -133,13 +135,13 @@ feature -- Item feature -- Parameter - string_item (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + string_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- String value for any variable of parameter `a_name' if relevant. do Result := string_from (item (a_name)) end - string_array_item (a_name: READABLE_STRING_8): detachable ARRAY [READABLE_STRING_32] + string_array_item (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32] -- Array of string values for query parameter `a_name' if relevant. do Result := string_array_for (a_name, agent string_item) @@ -147,32 +149,32 @@ feature -- Parameter feature -- Query parameter - query_parameter (a_name: READABLE_STRING_8): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Parameter value for query variable `a_name' --| i.e after the ? character do Result := request.query_parameter (a_name) end - string_query_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + string_query_parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- String value for query parameter `a_name' if relevant. do Result := string_from (query_parameter (a_name)) end - string_array_query_parameter (a_name: READABLE_STRING_8): detachable ARRAY [READABLE_STRING_32] + string_array_query_parameter (a_name: READABLE_STRING_GENERAL): detachable ARRAY [READABLE_STRING_32] -- Array of string values for query parameter `a_name' if relevant. do Result := string_array_for (a_name, agent string_query_parameter) end - is_integer_query_parameter (a_name: READABLE_STRING_8): BOOLEAN + is_integer_query_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN -- Is query parameter related to `a_name' an integer value? do Result := attached string_query_parameter (a_name) as s and then s.is_integer end - integer_query_parameter (a_name: READABLE_STRING_8): INTEGER + integer_query_parameter (a_name: READABLE_STRING_GENERAL): INTEGER -- Integer value for query parameter `a_name' if relevant. require is_integer_query_parameter: is_integer_query_parameter (a_name) @@ -202,7 +204,7 @@ feature -- Convertion feature {NONE} -- Implementation - string_array_for (a_name: READABLE_STRING_8; a_item_fct: FUNCTION [ANY, TUPLE [READABLE_STRING_8], detachable READABLE_STRING_32]): detachable ARRAY [READABLE_STRING_32] + string_array_for (a_name: READABLE_STRING_GENERAL; a_item_fct: FUNCTION [ANY, TUPLE [READABLE_STRING_GENERAL], detachable READABLE_STRING_32]): detachable ARRAY [READABLE_STRING_32] -- Array of string values for query parameter `a_name' if relevant. local i: INTEGER @@ -226,6 +228,14 @@ feature {NONE} -- Implementation Result.keep_head (n - 1) end +feature -- Status report + + debug_output: STRING + -- String that should be displayed in debugger to represent `Current'. + do + Result := path + end + ;note copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e b/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e index 2dc0340d..c45e5ede 100644 --- a/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e +++ b/library/server/wsf/src/mime/wsf_application_x_www_form_urlencoded_handler.e @@ -22,7 +22,7 @@ feature -- Status report feature -- Execution handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST; - a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8]) + a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]; a_raw_data: detachable CELL [detachable STRING_8]) local l_content: READABLE_STRING_8 n, p, i, j: INTEGER diff --git a/library/server/wsf/src/mime/wsf_mime_handler.e b/library/server/wsf/src/mime/wsf_mime_handler.e index af3b2470..66d579dc 100644 --- a/library/server/wsf/src/mime/wsf_mime_handler.e +++ b/library/server/wsf/src/mime/wsf_mime_handler.e @@ -16,7 +16,7 @@ feature -- Status report feature -- Execution handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST; - a_vars: TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8]) + a_vars: TABLE [WSF_VALUE, READABLE_STRING_GENERAL]; a_raw_data: detachable CELL [detachable STRING_8]) -- Handle MIME content from request `req', eventually fill the `a_vars' (not yet available from `req') -- and if `a_raw_data' is attached, store any read data inside `a_raw_data' require diff --git a/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e b/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e index 312f5fd5..1dcf27ee 100644 --- a/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e +++ b/library/server/wsf/src/mime/wsf_multipart_form_data_handler.e @@ -32,7 +32,7 @@ feature -- Status report feature -- Execution handle (a_content_type: HTTP_CONTENT_TYPE; req: WSF_REQUEST; - a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8]) + a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]; a_raw_data: detachable CELL [detachable STRING_8]) local s: like full_input_data do @@ -46,7 +46,7 @@ feature -- Execution feature {NONE} -- Implementation: Form analyzer - analyze_multipart_form (req: WSF_REQUEST; a_content_type: HTTP_CONTENT_TYPE; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) + analyze_multipart_form (req: WSF_REQUEST; a_content_type: HTTP_CONTENT_TYPE; s: READABLE_STRING_8; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]) -- Analyze multipart form content --| FIXME[2011-06-21]: integrate eMIME parser library require @@ -111,7 +111,7 @@ feature {NONE} -- Implementation: Form analyzer end end - analyze_multipart_form_input (req: WSF_REQUEST; s: STRING; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) + analyze_multipart_form_input (req: WSF_REQUEST; s: STRING; vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]) -- Analyze multipart entry require s_not_empty: s /= Void and then not s.is_empty diff --git a/library/server/wsf/src/support/wsf_mime_handler_helper.e b/library/server/wsf/src/support/wsf_mime_handler_helper.e index fff2cbcf..be149176 100644 --- a/library/server/wsf/src/support/wsf_mime_handler_helper.e +++ b/library/server/wsf/src/support/wsf_mime_handler_helper.e @@ -39,12 +39,12 @@ feature {NONE} -- Implementation 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_32]) + 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_32]) + 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 diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index b7df3a7f..632ea624 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -3,18 +3,18 @@ note Server request context of the httpd request It includes CGI interface and a few extra values that are usually valuable - meta_variable (a_name: READABLE_STRING_8): detachable WSF_STRING - meta_string_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + meta_variable (a_name: READABLE_STRING_GENERAL): detachable WSF_STRING + meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 In addition it provides - query_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE - form_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE - cookie (a_name: READABLE_STRING_8): detachable WSF_VALUE + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + form_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE ... And also has - execution_variable (a_name: READABLE_STRING_32): detachable ANY + execution_variable (a_name: READABLE_STRING_GENERAL): detachable ANY --| to keep value attached to the request ]" date: "$Date$" @@ -39,27 +39,25 @@ feature {NONE} -- Initialization tb: like meta_variables_table do wgi_request := r + create string_equality_tester if attached r.meta_variables as l_vars then - create tb.make (l_vars.count) + create tb.make_with_key_tester (l_vars.count, string_equality_tester) across l_vars as c loop tb.force (new_string_value (c.key, c.item), c.key) end else - create tb.make (0) + create tb.make_with_key_tester (0, string_equality_tester) end meta_variables_table := tb meta_variables := tb create error_handler.make - create uploaded_files_table.make (0) + create uploaded_files_table.make_with_key_tester (0, string_equality_tester) set_raw_input_data_recorded (False) create {STRING_32} empty_string.make_empty - create path_parameters_table.make (0) - path_parameters_table.compare_objects - - create execution_variables_table.make (0) + create execution_variables_table.make_with_key_tester (0, string_equality_tester) execution_variables_table.compare_objects initialize @@ -173,10 +171,10 @@ feature -- Access: Input feature -- Helper - is_request_method (m: READABLE_STRING_8): BOOLEAN + is_request_method (m: READABLE_STRING_GENERAL): BOOLEAN -- Is `m' the Current request_method? do - Result := request_method.is_case_insensitive_equal (m) + Result := request_method.is_case_insensitive_equal (m.as_string_8) end feature -- Eiffel WGI access @@ -203,29 +201,31 @@ feature -- Eiffel WGI access feature {NONE} -- Access: global variable - items_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + items_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] -- Table containing all the various variables -- Warning: this is computed each time, if you change the content of other containers -- this won't update this Result's content, unless you query it again do - create Result.make (100) + create Result.make_with_key_tester (20, string_equality_tester) - across - path_parameters as vars - loop - Result.force (vars.item, vars.item.name) + if attached path_parameters as l_path_parameters then + across + l_path_parameters as c + loop + Result.force (c.item, c.item.name) + end end across - query_parameters as vars + query_parameters as c loop - Result.force (vars.item, vars.item.name) + Result.force (c.item, c.item.name) end across - form_parameters as vars + form_parameters as c loop - Result.force (vars.item, vars.item.name) + Result.force (c.item, c.item.name) end end @@ -236,7 +236,7 @@ feature -- Access: global variable Result := items_table end - item (a_name: READABLE_STRING_32): detachable WSF_VALUE + item (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Variable named `a_name' from any of the variables container -- and following a specific order: form_, query_ and path_ parameters --| Cookie are not included due to security reason. @@ -250,7 +250,7 @@ feature -- Access: global variable end end - string_item (a_name: READABLE_STRING_32): detachable READABLE_STRING_32 + string_item (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 do if attached {WSF_STRING} item (a_name) as val then Result := val.string @@ -261,7 +261,7 @@ feature -- Access: global variable feature -- Execution variables - execution_variable (a_name: READABLE_STRING_32): detachable ANY + execution_variable (a_name: READABLE_STRING_GENERAL): detachable ANY -- Execution variable related to `a_name' require a_name_valid: a_name /= Void and then not a_name.is_empty @@ -269,14 +269,14 @@ feature -- Execution variables Result := execution_variables_table.item (a_name) end - set_execution_variable (a_name: READABLE_STRING_32; a_value: detachable ANY) + set_execution_variable (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY) do execution_variables_table.force (a_value, a_name) ensure param_set: execution_variable (a_name) = a_value end - unset_execution_variable (a_name: READABLE_STRING_32) + unset_execution_variable (a_name: READABLE_STRING_GENERAL) do execution_variables_table.remove (a_name) ensure @@ -285,11 +285,11 @@ feature -- Execution variables feature {NONE} -- Execution variables: implementation - execution_variables_table: HASH_TABLE [detachable ANY, READABLE_STRING_32] + execution_variables_table: HASH_TABLE_EX [detachable ANY, READABLE_STRING_GENERAL] feature -- Access: CGI Meta variables - meta_variable (a_name: READABLE_STRING_8): detachable WSF_STRING + meta_variable (a_name: READABLE_STRING_GENERAL): detachable WSF_STRING -- CGI Meta variable related to `a_name' require a_name_valid: a_name /= Void and then not a_name.is_empty @@ -297,7 +297,7 @@ feature -- Access: CGI Meta variables Result := meta_variables_table.item (a_name) end - meta_string_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_32 -- CGI meta variable related to `a_name' require a_name_valid: a_name /= Void and then not a_name.is_empty @@ -310,7 +310,7 @@ feature -- Access: CGI Meta variables meta_variables: ITERABLE [WSF_STRING] -- CGI meta variables values - meta_string_variable_or_default (a_name: READABLE_STRING_8; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32 + meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32 -- Value for meta parameter `a_name' -- If not found, return `a_default' require @@ -327,13 +327,15 @@ feature -- Access: CGI Meta variables end set_meta_string_variable (a_name: READABLE_STRING_8; a_value: READABLE_STRING_32) + -- Set meta variable `a_name' and `a_value' + --| `a_name' is READABLE_STRING_8 on purpose. do meta_variables_table.force (new_string_value (a_name, a_value), a_name) ensure param_set: attached {WSF_STRING} meta_variable (a_name) as val and then val.url_encoded_string.same_string (a_value) end - unset_meta_variable (a_name: READABLE_STRING_8) + unset_meta_variable (a_name: READABLE_STRING_GENERAL) do meta_variables_table.remove (a_name) ensure @@ -342,7 +344,7 @@ feature -- Access: CGI Meta variables feature {NONE} -- Access: CGI meta parameters - meta_variables_table: HASH_TABLE [WSF_STRING, READABLE_STRING_8] + meta_variables_table: HASH_TABLE_EX [WSF_STRING, READABLE_STRING_GENERAL] -- CGI Environment parameters feature -- Access: CGI meta parameters - 1.1 @@ -832,11 +834,12 @@ feature -- Extra CGI environment variables feature -- Cookies cookies: ITERABLE [WSF_VALUE] + -- All cookies. do Result := cookies_table end - cookie (a_name: READABLE_STRING_32): detachable WSF_VALUE + cookie (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Field for name `a_name'. do Result := cookies_table.item (a_name) @@ -844,7 +847,7 @@ feature -- Cookies feature {NONE} -- Cookies - cookies_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + cookies_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] -- Expanded cookies variable local i,j,p,n: INTEGER @@ -855,7 +858,7 @@ feature {NONE} -- Cookies if l_cookies = Void then if attached {WSF_STRING} meta_variable ({WSF_META_NAMES}.http_cookie) as val then s := val.string - create l_cookies.make (5) + create l_cookies.make_with_key_tester (5, string_equality_tester) l_cookies.compare_objects from n := s.count @@ -884,7 +887,7 @@ feature {NONE} -- Cookies end end else - create l_cookies.make (0) + create l_cookies.make_with_key_tester (0, string_equality_tester) l_cookies.compare_objects end internal_cookies_table := l_cookies @@ -894,76 +897,86 @@ feature {NONE} -- Cookies feature -- Path parameters - path_parameters: ITERABLE [WSF_VALUE] + path_parameters: detachable ITERABLE [WSF_VALUE] + -- All path parameters. + --| Could be Void do Result := path_parameters_table end - path_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE - -- Parameter for name `n'. + path_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + -- Path Parameter for name `a_name'. do - Result := path_parameters_table.item (a_name) - end - -feature -- Path parameters: Element change - - import_raw_path_parameters (lst: detachable TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8]) - -- The `path_parameters' are filled when known during the request handling - -- with table of urlencoded values - local - l_table: like path_parameters_table - do - create l_table.make (3) - path_parameters_table := l_table - - -- Remove existing previous values - l_table.wipe_out - if lst /= Void then - across - lst as c - loop - add_value_to_table (c.key, c.item, l_table) - end - end - end - - reset_path_parameters (vars: detachable like path_parameters) - local - l_table: like path_parameters_table - do - l_table := path_parameters_table - l_table.wipe_out - if vars /= Void then - across - vars as c - loop - l_table.force (c.item, c.item.name) - end + if attached path_parameters_table as tb then + Result := tb.item (a_name) end end feature {NONE} -- Query parameters: implementation - path_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] - -- Variables extracted from QUERY_STRING + path_parameters_table: detachable HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] + -- Parameters computed from `path_parameters_source' + --| most often coming from the associated route from WSF_ROUTER + +feature {WSF_REQUEST_PATH_PARAMETERS_SOURCE} -- Path parameters: Element change + + path_parameters_source: detachable WSF_REQUEST_PATH_PARAMETERS_SOURCE + -- Source of urlencoded path_parameters, or saved computed path parameters as WSF_VALUE. + + set_path_parameters_source (src: like path_parameters_source) + local + l_table: detachable like path_parameters_table + lst: detachable TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8] + l_count: INTEGER + do + path_parameters_source := src + if src = Void then + l_table := Void + else + l_count := src.path_parameters_count + if l_count = 0 then + l_table := Void + else + create l_table.make_with_key_tester (l_count, string_equality_tester) + l_table.compare_objects + if attached src.path_parameters as tb then + across + tb as c + loop + l_table.force (c.item, c.item.name) + end + else + lst := src.urlencoded_path_parameters + across + lst as c + loop + add_value_to_table (c.key, c.item, l_table) + end + src.update_path_parameters (l_table) + end + end + end + path_parameters_table := l_table + end feature -- Query parameters query_parameters: ITERABLE [WSF_VALUE] + -- All query parameters do Result := query_parameters_table end - query_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE - -- Parameter for name `n'. + query_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE + -- Query parameter for name `a_name'. do Result := query_parameters_table.item (a_name) end feature {NONE} -- Query parameters: implementation - query_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] - -- Variables extracted from QUERY_STRING + query_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] + -- Parameters extracted from QUERY_STRING local vars: like internal_query_parameters_table p,e: INTEGER @@ -993,7 +1006,7 @@ feature {NONE} -- Query parameters: implementation Result := vars end - urlencoded_parameters (a_content: detachable READABLE_STRING_8): HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + urlencoded_parameters (a_content: detachable READABLE_STRING_8): HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] -- Import `a_content' local n, p, i, j: INTEGER @@ -1001,13 +1014,13 @@ feature {NONE} -- Query parameters: implementation l_name, l_value: READABLE_STRING_8 do if a_content = Void then - create Result.make (0) + create Result.make_with_key_tester (0, string_equality_tester) else n := a_content.count if n = 0 then - create Result.make (0) + create Result.make_with_key_tester (0, string_equality_tester) else - create Result.make (3) + create Result.make_with_key_tester (3, string_equality_tester) --| 3 = arbitrary value from p := 1 until @@ -1034,92 +1047,6 @@ feature {NONE} -- Query parameters: implementation end end - 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: 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 - 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} 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) - else - a_table.force (create {WSF_MULTIPLE_STRING}.make_with_array (<>), 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 -- Form fields and related form_parameters: ITERABLE [WSF_VALUE] @@ -1127,7 +1054,7 @@ feature -- Form fields and related Result := form_parameters_table end - form_parameter (a_name: READABLE_STRING_32): detachable WSF_VALUE + form_parameter (a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Field for name `a_name'. do Result := form_parameters_table.item (a_name) @@ -1222,7 +1149,7 @@ feature {NONE} -- Implementation: MIME handler feature {NONE} -- Form fields and related - uploaded_files_table: HASH_TABLE [WSF_UPLOADED_FILE, READABLE_STRING_32] + uploaded_files_table: HASH_TABLE_EX [WSF_UPLOADED_FILE, READABLE_STRING_GENERAL] get_form_parameters -- Variables sent by POST, ... request @@ -1234,13 +1161,13 @@ feature {NONE} -- Form fields and related vars := internal_form_data_parameters_table if vars = Void then if not is_chunked_input and content_length_value = 0 then - create vars.make (0) + create vars.make_with_key_tester (0, string_equality_tester) vars.compare_objects else if raw_input_data_recorded then create l_raw_data_cell.put (Void) end - create vars.make (5) + create vars.make_with_key_tester (5, string_equality_tester) vars.compare_objects l_type := content_type @@ -1258,7 +1185,7 @@ feature {NONE} -- Form fields and related internal_form_data_parameters_table /= Void end - form_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + form_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL] -- Variables sent by POST request local vars: like internal_form_data_parameters_table @@ -1267,14 +1194,104 @@ feature {NONE} -- Form fields and related vars := internal_form_data_parameters_table if vars = Void then check form_parameters_already_retrieved: False end - create vars.make (0) + create vars.make_with_key_tester (0, string_equality_tester) end Result := vars end +feature {NONE} -- Implementation: smart parameter identification + + add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL]) + -- 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 + 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} 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) + else + a_table.force (create {WSF_MULTIPLE_STRING}.make_with_array (<>), 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 - is_uploaded_file (a_filename: STRING): BOOLEAN + is_uploaded_file (a_filename: READABLE_STRING_GENERAL): BOOLEAN -- Is `a_filename' a file uploaded via HTTP Form local l_files: like uploaded_files_table @@ -1286,7 +1303,7 @@ feature -- Uploaded File Handling until l_files.after or Result loop - if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string (a_filename) then + if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string_general (a_filename) then Result := True end l_files.forth @@ -1509,6 +1526,8 @@ feature {NONE} -- Implementation feature {NONE} -- Implementation: utilities + string_equality_tester: STRING_EQUALITY_TESTER + single_slash_starting_string (s: READABLE_STRING_32): STRING_32 -- Return the string `s' (or twin) with one and only one starting slash local diff --git a/library/server/wsf/src/wsf_request_path_parameters_source.e b/library/server/wsf/src/wsf_request_path_parameters_source.e new file mode 100644 index 00000000..61de2cce --- /dev/null +++ b/library/server/wsf/src/wsf_request_path_parameters_source.e @@ -0,0 +1,42 @@ +note + description: "Summary description for {WSF_REQUEST_PATH_PARAMETERS_SOURCE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_REQUEST_PATH_PARAMETERS_SOURCE + +feature -- Access + + path_parameters_count: INTEGER + deferred + end + + urlencoded_path_parameters: TABLE_ITERABLE [READABLE_STRING_8, READABLE_STRING_8] + -- Raw urlencoded path parameters. + deferred + end + + path_parameters: detachable ITERABLE [WSF_VALUE] + -- Computed path parameters according to the policy of WSF_REQUEST + +feature -- Element change + + update_path_parameters (lst: attached like path_parameters) + -- set computed `path_parameters' to `lst' + do + path_parameters := lst + end + +note + copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, 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