diff --git a/contrib/library/server/nino b/contrib/library/server/nino index ab38345c..e8521368 160000 --- a/contrib/library/server/nino +++ b/contrib/library/server/nino @@ -1 +1 @@ -Subproject commit ab38345c250308b937f75dbf1e626518f64e7eb5 +Subproject commit e85213689e33783eb6ad3233efa506318f0656ff diff --git a/examples/upload_image/htdocs/ewf.jpg b/examples/upload_image/htdocs/ewf.jpg new file mode 100644 index 00000000..4147dd9d Binary files /dev/null and b/examples/upload_image/htdocs/ewf.jpg differ diff --git a/examples/upload_image/htdocs/favicon.ico b/examples/upload_image/htdocs/favicon.ico new file mode 100644 index 00000000..2cb67ded Binary files /dev/null and b/examples/upload_image/htdocs/favicon.ico differ diff --git a/examples/upload_image/htdocs/files/do_not_remove b/examples/upload_image/htdocs/files/do_not_remove new file mode 100644 index 00000000..e69de29b diff --git a/examples/upload_image/htdocs/index.html b/examples/upload_image/htdocs/index.html new file mode 100644 index 00000000..a58cc5b7 --- /dev/null +++ b/examples/upload_image/htdocs/index.html @@ -0,0 +1,10 @@ + + + EWF: demo upload image file + + + +

EWF: demo upload image file

+ Click for the demo + + diff --git a/examples/upload_image/htdocs/style.css b/examples/upload_image/htdocs/style.css new file mode 100644 index 00000000..2a2faf74 --- /dev/null +++ b/examples/upload_image/htdocs/style.css @@ -0,0 +1,4 @@ +h1 { border: solid 1px #00f; margin: 5px; padding: 5px; background-color: #009; color: #fff; margin: 10px;} +form { border: solid 1px #999; margin: 20px; padding: 10px;} +img { width: 60%; } +img.hover { width: 100%; } diff --git a/examples/upload_image/src/image_uploader.e b/examples/upload_image/src/image_uploader.e new file mode 100644 index 00000000..fcf3fce1 --- /dev/null +++ b/examples/upload_image/src/image_uploader.e @@ -0,0 +1,197 @@ +note + description : "Objects that ..." + author : "$Author$" + date : "$Date$" + revision : "$Revision$" + +class + IMAGE_UPLOADER + +inherit + ANY + + URI_TEMPLATE_ROUTED_SERVICE + + ROUTED_SERVICE_HELPER + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize Current + local + s: DEFAULT_SERVICE_LAUNCHER + do + initialize_router + create s.make_and_launch (agent execute) + -- Use the following line to use particular port number (as 9090) with Nino connector + -- create s.make_and_launch_with_options (agent execute, <<["port", 9090]>>) + end + + create_router + -- Create router + do + create router.make (5) + end + + setup_router + -- Setup router + local + www: REQUEST_FILE_SYSTEM_HANDLER [REQUEST_URI_TEMPLATE_HANDLER_CONTEXT] + do + router.map_agent ("/upload{?nb}", agent execute_upload) + + create www.make (document_root) + www.set_directory_index (<<"index.html">>) + www.set_not_found_handler (agent execute_not_found) + router.map_with_request_methods ("{/path}{?query}", www, <<"GET">>) + end + +feature -- Configuration + + document_root: READABLE_STRING_8 + -- Document root to look for files or directories + local + e: EXECUTION_ENVIRONMENT + dn: DIRECTORY_NAME + once + create e + create dn.make_from_string (e.current_working_directory) + dn.extend ("htdocs") + Result := dn.string + if Result [Result.count] = Operating_environment.directory_separator then + Result := Result.substring (1, Result.count - 1) + end + end + + files_root: READABLE_STRING_8 + -- Uploaded files will be stored in `files_root' folder + local + dn: DIRECTORY_NAME + once + create dn.make_from_string (document_root) + dn.extend ("files") + Result := dn.string + end + +feature -- Execution + + execute_default (req: WSF_REQUEST; res: WSF_RESPONSE) + -- Default request handler if no other are relevant + do + res.redirect_now_with_content (req.script_url ("/"), "Redirection to " + req.script_url ("/"), "text/html") + end + + execute_not_found (uri: READABLE_STRING_8; ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) + -- `uri' is not found, redirect to default page + do + res.redirect_now_with_content (req.script_url ("/"), uri + ": not found.%NRedirection to " + req.script_url ("/"), "text/html") + end + + execute_upload (ctx: REQUEST_URI_TEMPLATE_HANDLER_CONTEXT; req: WSF_REQUEST; res: WSF_RESPONSE) + -- Upload page is requested, either GET or POST + -- On GET display the web form to upload file, by passing ?nb=5 you can upload 5 images + -- On POST display the uploaded files + local + l_body: STRING_8 + l_safe_filename: STRING_8 + fn: FILE_NAME + page: WSF_HTML_PAGE_RESPONSE + n: INTEGER + do + if req.is_request_method ("GET") or else not req.has_uploaded_file then + create page.make + page.set_title ("EWF: Upload file") + page.add_style (req.script_url ("style.css"), "all") + create l_body.make_empty + page.set_body (l_body) + l_body.append ("

EWF: Upload image file

%N") + l_body.append ("
%N") + if attached ctx.string_query_parameter ("nb") as p_nb and then p_nb.is_integer then + n := p_nb.to_integer + else + n := 1 + end + if attached ctx.string_query_parameter ("demo") as p_demo then + create fn.make_from_string (document_root) + fn.set_file_name (p_demo.string) + l_body.append ("File:
%N") + end + + from + until + n = 0 + loop + l_body.append ("File:
%N") + n := n - 1 + end + l_body.append (" %N
") + page.send_to (res) + else + create l_body.make (255) + l_body.append ("

EWF: Uploaded files

%N") + l_body.append ("") + + create page.make + page.set_title ("EWF: uploaded image") + page.add_style ("../style.css", "all") + page.set_body (l_body) + page.send_to (res) + end + end + +feature {NONE} -- Encoder + + url_encode (s: READABLE_STRING_32): STRING_8 + -- URL Encode `s' as Result + do + Result := url_encoder.encoded_string (s) + end + + url_encoder: URL_ENCODER + once + create Result + end + + html_encode (s: READABLE_STRING_32): STRING_8 + -- HTML Encode `s' as Result + do + Result := html_encoder.encoded_string (s) + end + + html_encoder: HTML_ENCODER + once + create Result + end + +note + copyright: "2011-2012, 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/examples/upload_image/upload_image-safe.ecf b/examples/upload_image/upload_image-safe.ecf new file mode 100644 index 00000000..8906381f --- /dev/null +++ b/examples/upload_image/upload_image-safe.ecf @@ -0,0 +1,31 @@ + + + + + + /EIFGENs$ + /\.git$ + /\.svn$ + + + + + + + + + + + + + + + + + + diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e index 72a51e7d..efd6b78b 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_connector.e @@ -117,7 +117,7 @@ feature -- Server process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET) local req: WGI_REQUEST_FROM_TABLE - res: detachable WGI_RESPONSE_STREAM + res: detachable WGI_NINO_RESPONSE_STREAM do create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current) create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket)) diff --git a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e index b707afb7..d11d2f7c 100644 --- a/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_input_stream.e @@ -77,11 +77,11 @@ feature -- Status report end_of_input: BOOLEAN -- Has the end of input stream been reached? do - Result := not source.ready_for_reading + Result := not source.try_ready_for_reading end ;note - copyright: "2011-2011, Eiffel Software and others" + copyright: "2011-2012, 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/ewsgi/connectors/nino/src/wgi_nino_response_stream.e b/library/server/ewsgi/connectors/nino/src/wgi_nino_response_stream.e new file mode 100644 index 00000000..c98789ff --- /dev/null +++ b/library/server/ewsgi/connectors/nino/src/wgi_nino_response_stream.e @@ -0,0 +1,45 @@ +note + description: "[ + WGI Response implemented using stream buffer + + ]" + date: "$Date$" + revision: "$Revision$" + +class + WGI_NINO_RESPONSE_STREAM + +inherit + WGI_RESPONSE_STREAM + redefine + put_header_text + end + +create + make + +feature -- Header output operation + + put_header_text (a_text: READABLE_STRING_8) + do + write (a_text) + -- Nino does not support persistent connection for now + write ("Connection: close") + write (crlf) + + -- end of headers + write (crlf) + header_committed := True + end + +;note + copyright: "2011-2012, 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/ewsgi/specification/request/wgi_uploaded_file_data.e b/library/server/ewsgi/specification/request/wgi_uploaded_file_data.e deleted file mode 100644 index 339febae..00000000 --- a/library/server/ewsgi/specification/request/wgi_uploaded_file_data.e +++ /dev/null @@ -1,103 +0,0 @@ -note - description: "Summary description for {WGI_UPLOADED_FILE_DATA}." - author: "" - date: "$Date$" - revision: "$Revision$" - -class - WGI_UPLOADED_FILE_DATA - -create - make - -feature {NONE} -- Initialization - - make (n: like name; t: like content_type; s: like size) - do - name := n - content_type := t - size := s - end - -feature -- Access - - name: STRING - -- original filename - - content_type: STRING - -- Content type - - size: INTEGER - -- Size of uploaded file - - tmp_name: detachable STRING - -- Filename of tmp file - - tmp_basename: detachable STRING - -- Basename of tmp file - -feature -- Basic operation - - move_to (a_destination: STRING): BOOLEAN - -- Move current uploaded file to `a_destination' - require - has_no_error: not has_error - local - f: RAW_FILE - do - if attached tmp_name as n then - create f.make (n) - if f.exists then - f.change_name (a_destination) - Result := True - end - end - end - -feature -- Status - - has_error: BOOLEAN - -- Has error during uploading - do - Result := error /= 0 - end - - error: INTEGER - -- Eventual error code - --| no error => 0 - -feature -- Element change - - set_error (e: like error) - -- Set `error' to `e' - do - error := e - end - - set_tmp_name (n: like tmp_name) - -- Set `tmp_name' to `n' - do - tmp_name := n - end - - set_tmp_basename (n: like tmp_basename) - -- Set `tmp_basename' to `n' - do - tmp_basename := n - end - -invariant - - valid_tmp_name: not has_error implies attached tmp_name as n and then not n.is_empty - -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/ewsgi/src/helper/wgi_request_from_table.e b/library/server/ewsgi/src/implementation/wgi_request_from_table.e similarity index 100% rename from library/server/ewsgi/src/helper/wgi_request_from_table.e rename to library/server/ewsgi/src/implementation/wgi_request_from_table.e diff --git a/library/server/ewsgi/src/helper/wgi_response_stream.e b/library/server/ewsgi/src/implementation/wgi_response_stream.e similarity index 100% rename from library/server/ewsgi/src/helper/wgi_response_stream.e rename to library/server/ewsgi/src/implementation/wgi_response_stream.e diff --git a/library/server/ewsgi/src/wgi_chunked_input_stream.e b/library/server/ewsgi/src/wgi_chunked_input_stream.e index e3699444..90db6692 100644 --- a/library/server/ewsgi/src/wgi_chunked_input_stream.e +++ b/library/server/ewsgi/src/wgi_chunked_input_stream.e @@ -20,7 +20,7 @@ feature {NONE} -- Implementation feature -- Input - data: READABLE_STRING_8 + data: STRING_8 local d: like internal_data do @@ -34,13 +34,13 @@ feature -- Input feature {NONE} -- Parser - internal_data: detachable READABLE_STRING_8 + internal_data: detachable STRING_8 tmp_hex_chunk_size: STRING_8 last_chunk_size: INTEGER last_chunk: detachable STRING_8 - fetched_data: READABLE_STRING_8 + fetched_data: STRING_8 -- Read all the data in a chunked stream. -- Make the result available in `last_chunked'. -- Chunked-Body = *chunk @@ -57,7 +57,7 @@ feature {NONE} -- Parser -- chunk-data = chunk-size(OCTET) -- trailer = *(entity-header CRLF) local - eoc : BOOLEAN + eoc: BOOLEAN s: STRING_8 do from @@ -69,7 +69,7 @@ feature {NONE} -- Parser if attached last_chunk as l_last_chunk then s.append (l_last_chunk) else - eoc := true + eoc := True end if last_chunk_size = 0 then eoc := True diff --git a/library/server/wsf/router/request_file_system_handler.e b/library/server/wsf/router/request_file_system_handler.e index fd973ee6..b9002556 100644 --- a/library/server/wsf/router/request_file_system_handler.e +++ b/library/server/wsf/router/request_file_system_handler.e @@ -31,6 +31,11 @@ feature -- Access directory_index: detachable ARRAY [READABLE_STRING_8] -- File serve if a directory index is requested + not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]] + + access_denied_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]] + + feature -- Element change set_directory_index (idx: like directory_index) @@ -43,6 +48,18 @@ feature -- Element change end end + set_not_found_handler (h: like not_found_handler) + -- Set `not_found_handler' to `h' + do + not_found_handler := h + end + + set_access_denied_handler (h: like access_denied_handler) + -- Set `access_denied_handler' to `h' + do + access_denied_handler := h + end + feature -- Execution execute (ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) @@ -168,15 +185,19 @@ feature -- Execution h: HTTP_HEADER s: STRING_8 do - create h.make - h.put_content_type_text_plain - create s.make_empty - s.append ("Resource %"" + uri + "%" not found%N") - res.set_status_code ({HTTP_STATUS_CODE}.not_found) - h.put_content_length (s.count) - res.put_header_text (h.string) - res.put_string (s) - res.flush + if attached not_found_handler as hdl then + hdl.call ([uri, ctx, req, res]) + else + create h.make + h.put_content_type_text_plain + create s.make_empty + s.append ("Resource %"" + uri + "%" not found%N") + res.set_status_code ({HTTP_STATUS_CODE}.not_found) + h.put_content_length (s.count) + res.put_header_text (h.string) + res.put_string (s) + res.flush + end end respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE) @@ -184,15 +205,19 @@ feature -- Execution h: HTTP_HEADER s: STRING_8 do - create h.make - h.put_content_type_text_plain - create s.make_empty - s.append ("Resource %"" + uri + "%": Access denied%N") - res.set_status_code ({HTTP_STATUS_CODE}.forbidden) - h.put_content_length (s.count) - res.put_header_text (h.string) - res.put_string (s) - res.flush + if attached access_denied_handler as hdl then + hdl.call ([uri, ctx, req, res]) + else + create h.make + h.put_content_type_text_plain + create s.make_empty + s.append ("Resource %"" + uri + "%": Access denied%N") + res.set_status_code ({HTTP_STATUS_CODE}.forbidden) + h.put_content_length (s.count) + res.put_header_text (h.string) + res.put_string (s) + res.flush + end end feature {NONE} -- Implementation diff --git a/library/server/wsf/router/request_handler_context.e b/library/server/wsf/router/request_handler_context.e index 90a80d5a..82799173 100644 --- a/library/server/wsf/router/request_handler_context.e +++ b/library/server/wsf/router/request_handler_context.e @@ -127,21 +127,50 @@ feature -- Query end end -feature -- String query +feature -- Convertion string_from (a_value: detachable WSF_VALUE): detachable READABLE_STRING_32 + -- String value from `a_value' if relevant. do if attached {WSF_STRING} a_value as val then Result := val.string end end + integer_from (a_value: detachable WSF_VALUE): INTEGER + -- String value from `a_value' if relevant. + do + if attached string_from (a_value) as val then + if val.is_integer then + Result := val.to_integer + end + end + end + +feature -- Path parameter + + is_integer_path_parameter (a_name: READABLE_STRING_8): 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 value for path parameter `a_name' if relevant. + require + is_integer_path_parameter: is_integer_path_parameter (a_name) + do + Result := integer_from (path_parameter (a_name)) + end + string_path_parameter (a_name: READABLE_STRING_8): 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] + -- Array of string values for path parameter `a_name' if relevant. local i: INTEGER n: INTEGER @@ -164,12 +193,56 @@ feature -- String query Result.keep_head (n - 1) end +feature -- String parameter + + is_integer_query_parameter (a_name: READABLE_STRING_8): 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 value for query parameter `a_name' if relevant. + require + is_integer_query_parameter: is_integer_query_parameter (a_name) + do + Result := integer_from (query_parameter (a_name)) + end + string_query_parameter (a_name: READABLE_STRING_8): 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] + -- Array of string values for query parameter `a_name' if relevant. + local + i: INTEGER + n: INTEGER + do + from + i := 1 + n := 1 + create Result.make_filled ("", 1, 5) + until + i = 0 + loop + if attached string_query_parameter (a_name + "[" + i.out + "]") as v then + Result.force (v, n) + n := n + 1 + i := i + 1 + else + i := 0 -- Exit + end + end + Result.keep_head (n - 1) + end + +feature -- Parameter + string_parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_32 + -- String value for path or query parameter `a_name' if relevant. do Result := string_from (parameter (a_name)) 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 index 32ad02fc..d66fad73 100644 --- a/library/server/wsf/src/request/value/visitor/wsf_value_iterator.e +++ b/library/server/wsf/src/request/value/visitor/wsf_value_iterator.e @@ -42,6 +42,9 @@ feature -- Visitor do end + process_uploaded_file (v: WSF_UPLOADED_FILE) + do + end ;note copyright: "2011-2011, Eiffel Software and others" 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 index f18dd979..6e801e23 100644 --- 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 @@ -29,6 +29,10 @@ feature -- Visitor do end + process_uploaded_file (v: WSF_UPLOADED_FILE) + do + 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/request/value/visitor/wsf_value_visitor.e b/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e index 0f5bceb4..58ad3fbc 100644 --- a/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e +++ b/library/server/wsf/src/request/value/visitor/wsf_value_visitor.e @@ -41,6 +41,12 @@ feature -- Visitor deferred end + process_uploaded_file (v: WSF_UPLOADED_FILE) + 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)" diff --git a/library/server/wsf/src/request/value/wsf_any.e b/library/server/wsf/src/request/value/wsf_any.e index 68d60fd9..92664d21 100644 --- a/library/server/wsf/src/request/value/wsf_any.e +++ b/library/server/wsf/src/request/value/wsf_any.e @@ -18,6 +18,7 @@ feature {NONE} -- Initialization make (a_name: READABLE_STRING_8; a_value: like item) do name := url_decoded_string (a_name) + url_encoded_name := a_name item := a_value end @@ -25,8 +26,19 @@ feature -- Access name: READABLE_STRING_32 + url_encoded_name: READABLE_STRING_8 + item: detachable ANY +feature -- Element change + + change_name (a_name: like name) + do + name := url_decoded_string (a_name) + ensure then + a_name.same_string (url_encoded_name) + end + feature -- Status report is_string: BOOLEAN = False @@ -43,7 +55,7 @@ feature -- Query else Result := "Void" end - end + end feature -- Visitor diff --git a/library/server/wsf/src/request/value/wsf_multiple_string.e b/library/server/wsf/src/request/value/wsf_multiple_string.e index e048cacc..8ee57398 100644 --- a/library/server/wsf/src/request/value/wsf_multiple_string.e +++ b/library/server/wsf/src/request/value/wsf_multiple_string.e @@ -65,6 +65,15 @@ feature -- Access Result := string_values.first end +feature -- Element change + + change_name (a_name: like name) + do + name := a_name + ensure then + a_name.same_string (name) + end + feature -- Status report is_string: BOOLEAN diff --git a/library/server/wsf/src/request/value/wsf_string.e b/library/server/wsf/src/request/value/wsf_string.e index 56ad96b3..a0abe2c3 100644 --- a/library/server/wsf/src/request/value/wsf_string.e +++ b/library/server/wsf/src/request/value/wsf_string.e @@ -37,9 +37,19 @@ feature -- Access string: READABLE_STRING_32 - url_encoded_name: READABLE_STRING_32 + url_encoded_name: READABLE_STRING_8 - url_encoded_string: READABLE_STRING_32 + url_encoded_string: READABLE_STRING_8 + +feature -- Element change + + change_name (a_name: like name) + do + name := url_decoded_string (a_name) + url_encoded_name := a_name + ensure then + a_name.same_string (url_encoded_name) + end feature -- Status report diff --git a/library/server/wsf/src/request/value/wsf_table.e b/library/server/wsf/src/request/value/wsf_table.e index 9bf17386..5533415f 100644 --- a/library/server/wsf/src/request/value/wsf_table.e +++ b/library/server/wsf/src/request/value/wsf_table.e @@ -24,13 +24,16 @@ feature {NONE} -- Initialization make (a_name: READABLE_STRING_8) do name := url_decoded_string (a_name) + url_encoded_name := a_name create values.make (5) end feature -- Access name: READABLE_STRING_32 - -- Parameter name + -- Parameter name + + url_encoded_name: READABLE_STRING_8 first_value: detachable WSF_VALUE -- First value if any. @@ -67,6 +70,16 @@ feature -- Access Result := values.count end +feature -- Element change + + change_name (a_name: like name) + do + name := url_decoded_string (a_name) + url_encoded_name := a_name + ensure then + a_name.same_string (url_encoded_name) + end + feature -- Status report is_string: BOOLEAN diff --git a/library/server/wsf/src/request/value/wsf_uploaded_file.e b/library/server/wsf/src/request/value/wsf_uploaded_file.e new file mode 100644 index 00000000..43b21729 --- /dev/null +++ b/library/server/wsf/src/request/value/wsf_uploaded_file.e @@ -0,0 +1,217 @@ +note + description: "Summary description for {WSF_UPLOADED_FILE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_UPLOADED_FILE + +inherit + WSF_VALUE + +create + make + +feature {NONE} -- Initialization + + make (a_name: READABLE_STRING_8; n: like filename; t: like content_type; s: like size) + do + name := url_decoded_string (a_name) + url_encoded_name := a_name + filename := n + content_type := t + size := s + end + +feature -- Access + + name: READABLE_STRING_32 + + url_encoded_name: READABLE_STRING_8 + +feature -- Element change + + change_name (a_name: like name) + do + name := url_decoded_string (a_name) + url_encoded_name := a_name + ensure then + a_name.same_string (url_encoded_name) + end + + +feature -- Status report + + is_string: BOOLEAN = False + -- Is Current as a WSF_STRING representation? + + +feature -- Conversion + + string_representation: STRING_32 + do + Result := filename + end + +feature -- Visitor + + process (vis: WSF_VALUE_VISITOR) + do + vis.process_uploaded_file (Current) + end + +feature -- Access: Uploaded File + + filename: STRING + -- original filename + + content_type: STRING + -- Content type + + size: INTEGER + -- Size of uploaded file + + tmp_name: detachable STRING + -- Filename of tmp file + + tmp_basename: detachable STRING + -- Basename of tmp file + +feature -- Conversion + + safe_filename: STRING + local + fn: like filename + c: CHARACTER + i, n: INTEGER + do + fn := filename + + --| Compute safe filename, to avoid creating impossible filename, or dangerous one + from + i := 1 + n := fn.count + create Result.make (n) + until + i > n + loop + c := fn[i] + inspect c + when '.', '-', '_' then + Result.extend (c) + when 'A' .. 'Z', 'a' .. 'z', '0' .. '9' then + Result.extend (c) + else + inspect c + when '%/192/' then Result.extend ('A') -- À + when '%/193/' then Result.extend ('A') -- Á + when '%/194/' then Result.extend ('A') -- Â + when '%/195/' then Result.extend ('A') -- Ã + when '%/196/' then Result.extend ('A') -- Ä + when '%/197/' then Result.extend ('A') -- Å + when '%/199/' then Result.extend ('C') -- Ç + when '%/200/' then Result.extend ('E') -- È + when '%/201/' then Result.extend ('E') -- É + when '%/202/' then Result.extend ('E') -- Ê + when '%/203/' then Result.extend ('E') -- Ë + when '%/204/' then Result.extend ('I') -- Ì + when '%/205/' then Result.extend ('I') -- Í + when '%/206/' then Result.extend ('I') -- Î + when '%/207/' then Result.extend ('I') -- Ï + when '%/210/' then Result.extend ('O') -- Ò + when '%/211/' then Result.extend ('O') -- Ó + when '%/212/' then Result.extend ('O') -- Ô + when '%/213/' then Result.extend ('O') -- Õ + when '%/214/' then Result.extend ('O') -- Ö + when '%/217/' then Result.extend ('U') -- Ù + when '%/218/' then Result.extend ('U') -- Ú + when '%/219/' then Result.extend ('U') -- Û + when '%/220/' then Result.extend ('U') -- Ü + when '%/221/' then Result.extend ('Y') -- Ý + when '%/224/' then Result.extend ('a') -- à + when '%/225/' then Result.extend ('a') -- á + when '%/226/' then Result.extend ('a') -- â + when '%/227/' then Result.extend ('a') -- ã + when '%/228/' then Result.extend ('a') -- ä + when '%/229/' then Result.extend ('a') -- å + when '%/231/' then Result.extend ('c') -- ç + when '%/232/' then Result.extend ('e') -- è + when '%/233/' then Result.extend ('e') -- é + when '%/234/' then Result.extend ('e') -- ê + when '%/235/' then Result.extend ('e') -- ë + when '%/236/' then Result.extend ('i') -- ì + when '%/237/' then Result.extend ('i') -- í + when '%/238/' then Result.extend ('i') -- î + when '%/239/' then Result.extend ('i') -- ï + when '%/240/' then Result.extend ('o') -- ð + when '%/242/' then Result.extend ('o') -- ò + when '%/243/' then Result.extend ('o') -- ó + when '%/244/' then Result.extend ('o') -- ô + when '%/245/' then Result.extend ('o') -- õ + when '%/246/' then Result.extend ('o') -- ö + when '%/249/' then Result.extend ('u') -- ù + when '%/250/' then Result.extend ('u') -- ú + when '%/251/' then Result.extend ('u') -- û + when '%/252/' then Result.extend ('u') -- ü + when '%/253/' then Result.extend ('y') -- ý + when '%/255/' then Result.extend ('y') -- ÿ + else + Result.extend ('-') + end + end + i := i + 1 + end + end + +feature -- Basic operation + + move_to (a_destination: STRING): BOOLEAN + -- Move current uploaded file to `a_destination' + require + has_no_error: not has_error + local + f: RAW_FILE + do + if attached tmp_name as n then + create f.make (n) + if f.exists then + f.change_name (a_destination) + Result := True + end + end + end + +feature -- Status + + has_error: BOOLEAN + -- Has error during uploading + do + Result := error /= 0 + end + + error: INTEGER + -- Eventual error code + --| no error => 0 + +feature -- Element change + + set_error (e: like error) + -- Set `error' to `e' + do + error := e + end + + set_tmp_name (n: like tmp_name) + -- Set `tmp_name' to `n' + do + tmp_name := n + end + + set_tmp_basename (n: like tmp_basename) + -- Set `tmp_basename' to `n' + do + tmp_basename := n + end + +end diff --git a/library/server/wsf/src/request/wsf_value.e b/library/server/wsf/src/request/wsf_value.e index 5a7a51df..7296f8fd 100644 --- a/library/server/wsf/src/request/wsf_value.e +++ b/library/server/wsf/src/request/wsf_value.e @@ -16,6 +16,13 @@ feature -- Access deferred end +feature -- Element change + + change_name (a_name: like name) + -- Change parameter name + deferred + end + feature -- Status report is_string: BOOLEAN diff --git a/library/server/wsf/src/response/wsf_html_page_response.e b/library/server/wsf/src/response/wsf_html_page_response.e new file mode 100644 index 00000000..07be5263 --- /dev/null +++ b/library/server/wsf/src/response/wsf_html_page_response.e @@ -0,0 +1,171 @@ +note + description: "Summary description for {WSF_PAGE_RESPONSE}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_HTML_PAGE_RESPONSE + +inherit + WSF_RESPONSE_MESSAGE + +create + make + +feature {NONE} -- Initialization + + make + do + status_code := {HTTP_STATUS_CODE}.ok + create header.make + create {ARRAYED_LIST [STRING]} head_lines.make (5) + doctype := "" + header.put_content_type_text_html + end + +feature -- Status + + status_code: INTEGER + +feature -- Header + + header: HTTP_HEADER + +feature -- Html access + + doctype: STRING + + language: detachable STRING + + title: detachable STRING + + head_lines: LIST [STRING] + + body: detachable STRING + +feature -- Element change + + set_status_code (c: like status_code) + do + status_code := c + end + + set_language (s: like language) + do + language := s + end + + set_title (s: like title) + do + title := s + end + + add_meta_name_content (a_name: STRING; a_content: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_style (a_href: STRING; a_media: detachable STRING) + local + s: STRING_8 + do + s := "") + head_lines.extend (s) + end + + add_javascript_url (a_src: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + add_javascript_content (a_script: STRING) + local + s: STRING_8 + do + s := "" + head_lines.extend (s) + end + + set_body (b: like body) + do + body := b + end + +feature -- Output + + send_to (res: WSF_RESPONSE) + local + t: like title + lines: like head_lines + b: like body + h: like header + s: STRING_8 + do + create s.make (64) + if attached doctype as l_doctype then + s.append (l_doctype) + s.append_character ('%N') + end + s.append ("%N") + + t := title + lines := head_lines + if t /= Void or else lines.count > 0 then + s.append ("") + if t /= Void then + s.append ("" + t + "%N") + end + s.append_character ('%N') + across + lines as l + loop + s.append (l.item) + s.append_character ('%N') + end + s.append ("%N") + end + + b := body + s.append ("%N") + if b /= Void then + s.append (b) + end + s.append ("%N%N") + + h := header + res.set_status_code (status_code) + + if not h.has_content_length then + h.put_content_length (s.count) + end + if not h.has_content_type then + h.put_content_type_text_html + end + res.put_header_text (h.string) + res.put_string (s) + end + +end 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 ca554ed6..bc057d4b 100644 --- a/library/server/wsf/src/support/wsf_mime_handler_helper.e +++ b/library/server/wsf/src/support/wsf_mime_handler_helper.e @@ -23,20 +23,18 @@ feature {NONE} -- Implementation end end - read_input_data (a_input: WGI_INPUT_STREAM; nb: NATURAL_64): READABLE_STRING_8 + read_input_data (a_input: WGI_INPUT_STREAM; nb: NATURAL_64): STRING_8 -- All data from input form local nb32: INTEGER n64: NATURAL_64 n: INTEGER t: STRING - s: STRING_8 do from n64 := nb nb32 := n64.to_integer_32 - create s.make (nb32) - Result := s + create Result.make (nb32) n := nb32 if n > 1_024 then n := 1_024 @@ -46,7 +44,7 @@ feature {NONE} -- Implementation loop a_input.read_string (n) t := a_input.last_string - s.append_string (t) + Result.append_string (t) if t.count < n then n64 := 0 else @@ -55,7 +53,12 @@ feature {NONE} -- 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]) + add_string_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]) + 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]) local l_decoded_name: STRING_32 v: detachable WSF_VALUE @@ -121,13 +124,15 @@ feature {NONE} -- Implementation --| Ignore bad value end end - tb.add_value (new_string_value (n, a_value), k) + a_value.change_name (n) + tb.add_value (a_value, k) else --| Missing end bracket end end if v = Void then - v := new_string_value (a_name, a_value) + 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 diff --git a/library/server/wsf/src/wsf_application_x_www_form_urlencoded_handler.e b/library/server/wsf/src/wsf_application_x_www_form_urlencoded_handler.e index 3433b6a7..308debde 100644 --- a/library/server/wsf/src/wsf_application_x_www_form_urlencoded_handler.e +++ b/library/server/wsf/src/wsf_application_x_www_form_urlencoded_handler.e @@ -54,7 +54,7 @@ feature -- Execution if j > 0 then l_name := s.substring (1, j - 1) l_value := s.substring (j + 1, s.count) - add_value_to_table (l_name, l_value, a_vars) + add_string_value_to_table (l_name, l_value, a_vars) end end end diff --git a/library/server/wsf/src/wsf_multipart_form_data_handler.e b/library/server/wsf/src/wsf_multipart_form_data_handler.e index edc15afe..fc20b675 100644 --- a/library/server/wsf/src/wsf_multipart_form_data_handler.e +++ b/library/server/wsf/src/wsf_multipart_form_data_handler.e @@ -46,7 +46,7 @@ feature -- Execution handle (a_content_type: READABLE_STRING_8; req: WSF_REQUEST; a_vars: HASH_TABLE [WSF_VALUE, READABLE_STRING_32]; a_raw_data: detachable CELL [detachable STRING_8]) local - s: READABLE_STRING_8 + s: like full_input_data do s := full_input_data (req) if a_raw_data /= Void then @@ -134,7 +134,7 @@ feature {NONE} -- Implementation: Form analyzer l_header: detachable STRING_8 l_content: detachable STRING_8 l_line: detachable STRING_8 - l_up_file_info: WGI_UPLOADED_FILE_DATA + l_up_file: WSF_UPLOADED_FILE do from p := 1 @@ -223,15 +223,16 @@ feature {NONE} -- Implementation: Form analyzer end end if l_name /= Void then - if l_filename /= Void then + if l_filename /= Void and then not l_filename.is_empty then if l_content_type = Void then l_content_type := default_content_type end - create l_up_file_info.make (l_filename, l_content_type, l_content.count) - req.save_uploaded_file (l_content, l_up_file_info) - req.uploaded_files.force (l_up_file_info, l_name) + create l_up_file.make (l_name, l_filename, l_content_type, l_content.count) + add_value_to_table (l_name, l_up_file, vars) + --| `l_up_file' might have a new name + req.save_uploaded_file (l_up_file, l_content) else - add_value_to_table (l_name, l_content, vars) + add_string_value_to_table (l_name, l_content, vars) end else error_handler.add_custom_error (0, "unamed multipart entry", Void) diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e index be77a412..3684d9a2 100644 --- a/library/server/wsf/src/wsf_request.e +++ b/library/server/wsf/src/wsf_request.e @@ -52,8 +52,8 @@ feature {NONE} -- Initialization meta_variables_table := tb meta_variables := tb create error_handler.make - create uploaded_files.make (0) - raw_post_data_recorded := True + create uploaded_files_table.make (0) + set_raw_input_data_recorded (False) create {STRING_32} empty_string.make_empty create execution_variables_table.make (0) @@ -94,6 +94,21 @@ feature {NONE} -- Initialization wgi_request: WGI_REQUEST +feature -- Destroy + + destroy + -- Destroy the object when request is completed + do + -- Removed uploaded files + across + -- Do not use `uploaded_files' directly + -- just to avoid processing input data if not yet done + uploaded_files_table as c + loop + delete_uploaded_file (c.item) + end + end + feature -- Status report debug_output: STRING_8 @@ -101,14 +116,24 @@ feature -- Status report create Result.make_from_string (request_method + " " + request_uri) end -feature -- Status +feature -- Setting - raw_post_data_recorded: BOOLEAN assign set_raw_post_data_recorded - -- Record RAW POST DATA in meta parameters + raw_input_data_recorded: BOOLEAN assign set_raw_input_data_recorded + -- Record RAW Input datas into `raw_input_data' -- otherwise just forget about it - -- Default: true + -- Default: False --| warning: you might keep in memory big amount of memory ... +feature -- Raw input data + + raw_input_data: detachable READABLE_STRING_8 + -- Raw input data is `raw_input_data_recorded' is True + + set_raw_input_data (d: READABLE_STRING_8) + do + raw_input_data := d + end + feature -- Error handling has_error: BOOLEAN @@ -1055,18 +1080,6 @@ feature {NONE} -- Query parameters: implementation feature -- Form fields and related - form_data_parameters: like form_parameters - obsolete "[2011-oct-24] Use form_parameters" - do - Result := form_parameters - end - - 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 @@ -1078,14 +1091,30 @@ feature -- Form fields and related Result := form_parameters_table.item (a_name) end - uploaded_files: HASH_TABLE [WGI_UPLOADED_FILE_DATA, STRING] - -- Table of uploaded files information - --| name: original path from the user + has_uploaded_file: BOOLEAN + -- Has any uploaded file? + do + -- Be sure, the `form_parameters' are already processed + get_form_parameters + + Result := not uploaded_files_table.is_empty + end + + uploaded_files: ITERABLE [WSF_UPLOADED_FILE] + -- uploaded files values + --| filename: original path from the user --| type: content type --| tmp_name: path to temp file that resides on server --| tmp_base_name: basename of `tmp_name' --| error: if /= 0 , there was an error : TODO ... --| size: size of the file given by the http request + do + -- Be sure, the `form_parameters' are already processed + get_form_parameters + + -- return uploaded files table + Result := uploaded_files_table + end feature -- Access: MIME handler @@ -1151,8 +1180,10 @@ feature {NONE} -- Implementation: MIME handler feature {NONE} -- Form fields and related - form_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] - -- Variables sent by POST request + uploaded_files_table: HASH_TABLE [WSF_UPLOADED_FILE, READABLE_STRING_32] + + get_form_parameters + -- Variables sent by POST, ... request local vars: like internal_form_data_parameters_table l_raw_data_cell: detachable CELL [detachable STRING_8] @@ -1164,7 +1195,7 @@ feature {NONE} -- Form fields and related create vars.make (0) vars.compare_objects else - if raw_post_data_recorded then + if raw_input_data_recorded then create l_raw_data_cell.put (Void) end create vars.make (5) @@ -1176,11 +1207,26 @@ feature {NONE} -- Form fields and related end if l_raw_data_cell /= Void and then attached l_raw_data_cell.item as l_raw_data then -- What if no mime handler is associated to `l_type' ? - set_meta_string_variable ("RAW_POST_DATA", l_raw_data) + set_raw_input_data (l_raw_data) end end internal_form_data_parameters_table := vars end + ensure + internal_form_data_parameters_table /= Void + end + + form_parameters_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_32] + -- Variables sent by POST request + local + vars: like internal_form_data_parameters_table + do + get_form_parameters + vars := internal_form_data_parameters_table + if vars = Void then + check form_parameters_already_retrieved: False end + create vars.make (0) + end Result := vars end @@ -1189,9 +1235,9 @@ feature -- Uploaded File Handling is_uploaded_file (a_filename: STRING): BOOLEAN -- Is `a_filename' a file uploaded via HTTP Form local - l_files: like uploaded_files + l_files: like uploaded_files_table do - l_files := uploaded_files + l_files := uploaded_files_table if not l_files.is_empty then from l_files.start @@ -1278,10 +1324,10 @@ feature {NONE} -- Implementation: URL Utility feature -- Element change - set_raw_post_data_recorded (b: BOOLEAN) - -- Set `raw_post_data_recorded' to `b' + set_raw_input_data_recorded (b: BOOLEAN) + -- Set `raw_input_data_recorded' to `b' do - raw_post_data_recorded := b + raw_input_data_recorded := b end set_error_handler (ehdl: like error_handler) @@ -1292,14 +1338,14 @@ feature -- Element change feature {WSF_MIME_HANDLER} -- Temporary File handling - delete_uploaded_file (uf: WGI_UPLOADED_FILE_DATA) + delete_uploaded_file (uf: WSF_UPLOADED_FILE) -- Delete file `a_filename' require uf_valid: uf /= Void local f: RAW_FILE do - if uploaded_files.has_item (uf) then + if uploaded_files_table.has_item (uf) then if attached uf.tmp_name as fn then create f.make (fn) if f.exists and then f.is_writable then @@ -1315,7 +1361,7 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling end end - save_uploaded_file (a_content: STRING; a_up_fn_info: WGI_UPLOADED_FILE_DATA) + save_uploaded_file (a_up_file: WSF_UPLOADED_FILE; a_content: STRING) -- Save uploaded file content to `a_filename' local bn: STRING @@ -1328,10 +1374,11 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling rescued: BOOLEAN do if not rescued then + -- FIXME: should it be configured somewhere? dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory create d.make (dn) if d.exists and then d.is_writable then - l_safe_name := safe_filename (a_up_fn_info.name) + l_safe_name := a_up_file.safe_filename from create fn.make_from_string (dn) bn := "tmp-" + l_safe_name @@ -1350,106 +1397,26 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling end if not f.exists or else f.is_writable then - a_up_fn_info.set_tmp_name (f.name) - a_up_fn_info.set_tmp_basename (bn) + a_up_file.set_tmp_name (f.name) + a_up_file.set_tmp_basename (bn) f.open_write f.put_string (a_content) f.close else - a_up_fn_info.set_error (-1) + a_up_file.set_error (-1) end else error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"") end + uploaded_files_table.force (a_up_file, a_up_file.name) else - a_up_fn_info.set_error (-1) + a_up_file.set_error (-1) end rescue rescued := True retry end - safe_filename (fn: STRING): STRING - local - c: CHARACTER - i, n: INTEGER - do - --| Compute safe filename, to avoid creating impossible filename, or dangerous one - from - i := 1 - n := fn.count - create Result.make (n) - until - i > n - loop - c := fn[i] - inspect c - when '.', '-', '_' then - Result.extend (c) - when 'A' .. 'Z', 'a' .. 'z', '0' .. '9' then - Result.extend (c) - else - inspect c - when '%/192/' then Result.extend ('A') -- À - when '%/193/' then Result.extend ('A') -- Á - when '%/194/' then Result.extend ('A') -- Â - when '%/195/' then Result.extend ('A') -- Ã - when '%/196/' then Result.extend ('A') -- Ä - when '%/197/' then Result.extend ('A') -- Å - when '%/199/' then Result.extend ('C') -- Ç - when '%/200/' then Result.extend ('E') -- È - when '%/201/' then Result.extend ('E') -- É - when '%/202/' then Result.extend ('E') -- Ê - when '%/203/' then Result.extend ('E') -- Ë - when '%/204/' then Result.extend ('I') -- Ì - when '%/205/' then Result.extend ('I') -- Í - when '%/206/' then Result.extend ('I') -- Î - when '%/207/' then Result.extend ('I') -- Ï - when '%/210/' then Result.extend ('O') -- Ò - when '%/211/' then Result.extend ('O') -- Ó - when '%/212/' then Result.extend ('O') -- Ô - when '%/213/' then Result.extend ('O') -- Õ - when '%/214/' then Result.extend ('O') -- Ö - when '%/217/' then Result.extend ('U') -- Ù - when '%/218/' then Result.extend ('U') -- Ú - when '%/219/' then Result.extend ('U') -- Û - when '%/220/' then Result.extend ('U') -- Ü - when '%/221/' then Result.extend ('Y') -- Ý - when '%/224/' then Result.extend ('a') -- à - when '%/225/' then Result.extend ('a') -- á - when '%/226/' then Result.extend ('a') -- â - when '%/227/' then Result.extend ('a') -- ã - when '%/228/' then Result.extend ('a') -- ä - when '%/229/' then Result.extend ('a') -- å - when '%/231/' then Result.extend ('c') -- ç - when '%/232/' then Result.extend ('e') -- è - when '%/233/' then Result.extend ('e') -- é - when '%/234/' then Result.extend ('e') -- ê - when '%/235/' then Result.extend ('e') -- ë - when '%/236/' then Result.extend ('i') -- ì - when '%/237/' then Result.extend ('i') -- í - when '%/238/' then Result.extend ('i') -- î - when '%/239/' then Result.extend ('i') -- ï - when '%/240/' then Result.extend ('o') -- ð - when '%/242/' then Result.extend ('o') -- ò - when '%/243/' then Result.extend ('o') -- ó - when '%/244/' then Result.extend ('o') -- ô - when '%/245/' then Result.extend ('o') -- õ - when '%/246/' then Result.extend ('o') -- ö - when '%/249/' then Result.extend ('u') -- ù - when '%/250/' then Result.extend ('u') -- ú - when '%/251/' then Result.extend ('u') -- û - when '%/252/' then Result.extend ('u') -- ü - when '%/253/' then Result.extend ('y') -- ý - when '%/255/' then Result.extend ('y') -- ÿ - else - Result.extend ('-') - end - end - i := i + 1 - end - end - feature {WSF_MIME_HANDLER} -- Input data access form_input_data (nb: NATURAL_64): READABLE_STRING_8 diff --git a/library/server/wsf/src/wsf_response.e b/library/server/wsf/src/wsf_response.e index 5fc4a69e..be214460 100644 --- a/library/server/wsf/src/wsf_response.e +++ b/library/server/wsf/src/wsf_response.e @@ -115,40 +115,8 @@ feature -- Header output operation wgi_response.put_header_lines (a_lines) end -feature -- Obsolete: Header output operation - - write_header_text (a_headers: READABLE_STRING_8) - obsolete "[2011-dec-15] use put_header_text" - do - put_header_text (a_headers) - end - - write_header (a_status_code: INTEGER; a_headers: detachable ARRAY [TUPLE [key: READABLE_STRING_8; value: READABLE_STRING_8]]) - obsolete "[2011-dec-15] use put_header" - do - put_header (a_status_code, a_headers) - end - - write_header_lines (a_lines: ITERABLE [TUPLE [name: READABLE_STRING_8; value: READABLE_STRING_8]]) - obsolete "[2011-dec-15] use put_header_lines" - do - put_header_lines (a_lines) - end - feature -- Output operation - write_string (s: READABLE_STRING_8) - obsolete "[2011-dec-15] use put_string" - do - put_string (s) - end - - write_substring (s: READABLE_STRING_8; a_begin_index, a_end_index: INTEGER) - obsolete "[2011-dec-15] use put_substring" - do - put_substring (s, a_begin_index, a_end_index) - end - put_string (s: READABLE_STRING_8) -- Send the string `s' require @@ -205,6 +173,12 @@ feature -- Output operation flush end + put_chunk_end + -- Put end of chunked content + do + put_chunk (Void, Void) + end + flush -- Flush if it makes sense do @@ -244,7 +218,7 @@ feature -- Redirect end h.put_location (a_url) if a_status_code = 0 then - set_status_code ({HTTP_STATUS_CODE}.moved_permanently) + set_status_code ({HTTP_STATUS_CODE}.temp_redirect) else set_status_code (a_status_code) end @@ -265,13 +239,13 @@ feature -- Redirect require header_not_committed: not header_committed do - redirect_now_custom (a_url, {HTTP_STATUS_CODE}.moved_permanently, Void, Void) + redirect_now_custom (a_url, {HTTP_STATUS_CODE}.temp_redirect, Void, Void) end redirect_now_with_content (a_url: READABLE_STRING_8; a_content: READABLE_STRING_8; a_content_type: READABLE_STRING_8) -- Redirect to the given url `a_url' do - redirect_now_custom (a_url, {HTTP_STATUS_CODE}.moved_permanently, Void, [a_content, a_content_type]) + redirect_now_custom (a_url, {HTTP_STATUS_CODE}.temp_redirect, Void, [a_content, a_content_type]) end note diff --git a/library/server/wsf/src/wsf_service.e b/library/server/wsf/src/wsf_service.e index c2b36e0e..2a48df75 100644 --- a/library/server/wsf/src/wsf_service.e +++ b/library/server/wsf/src/wsf_service.e @@ -31,13 +31,19 @@ feature {WGI_CONNECTOR} -- WGI Execution wgi_execute (req: WGI_REQUEST; res: WGI_RESPONSE) local w_res: detachable WSF_RESPONSE + w_req: detachable WSF_REQUEST do create w_res.make_from_wgi (res) - execute (create {WSF_REQUEST}.make_from_wgi (req), w_res) + create w_req.make_from_wgi (req) + execute (w_req, w_res) + w_req.destroy rescue if w_res /= Void then w_res.flush end + if w_req /= Void then + w_req.destroy + end end end