Nino connector:
- fixed issue related to `ready_for_reading' now use the `try_...' variant - for now Nino does not support persistent connection, then we have to respond with "Connection: close" REQUEST_FILE_SYSTEM_HANDLER: - added not_found_handler and access_denied_handler, so that the user can customize related response WSF_REQUEST and WSF_VALUE: - modified how uploaded file are handled, fixed various issues, and added WSF_UPLOADED_FILE (it is a WSF_VALUE) WSF_VALUE: - added change_name (a_name: like name) - added url_encoded_name to other WSF_values WSF_REQUEST: - added `destroy' to perform end of request cleaning (such as deleting temp uploaded files) - renamed `raw_post_data_recorded' as `raw_input_data_recorded', and related feature - do not store the RAW_POST_DATA in meta variable anymore, but in WSF_REQUEST.raw_input_data is asked Added WSF_HTML_PAGE_RESPONSE to help user WSF_REPONSE.redirect_... now use "temp_redirect" as default instead of "moved_permanently" which is specific usage Removed many obsolete features.
This commit is contained in:
Submodule contrib/library/server/nino updated: ab38345c25...e85213689e
BIN
examples/upload_image/htdocs/ewf.jpg
Normal file
BIN
examples/upload_image/htdocs/ewf.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
examples/upload_image/htdocs/favicon.ico
Normal file
BIN
examples/upload_image/htdocs/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.9 KiB |
0
examples/upload_image/htdocs/files/do_not_remove
Normal file
0
examples/upload_image/htdocs/files/do_not_remove
Normal file
10
examples/upload_image/htdocs/index.html
Normal file
10
examples/upload_image/htdocs/index.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>EWF: demo upload image file</title>
|
||||
<link rel="stylesheet" href="style.css" type="text/css" media="all" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>EWF: demo upload image file</h1>
|
||||
<a href="upload">Click for the demo</a>
|
||||
</body>
|
||||
</html>
|
||||
4
examples/upload_image/htdocs/style.css
Normal file
4
examples/upload_image/htdocs/style.css
Normal file
@@ -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%; }
|
||||
197
examples/upload_image/src/image_uploader.e
Normal file
197
examples/upload_image/src/image_uploader.e
Normal file
@@ -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 ("<h1>EWF: Upload image file</h1>%N")
|
||||
l_body.append ("<form action=%""+ req.script_url ("/upload") +"%" method=%"POST%" enctype=%"multipart/form-data%">%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: <input type=%"file%" name=%"uploaded_file[]%" size=%"60%" value=%""+ html_encode (fn.string) +"%"></br>%N")
|
||||
end
|
||||
|
||||
from
|
||||
until
|
||||
n = 0
|
||||
loop
|
||||
l_body.append ("File: <input type=%"file%" name=%"uploaded_file[]%" size=%"60%" accept=%"image/*%"></br>%N")
|
||||
n := n - 1
|
||||
end
|
||||
l_body.append (" <input type=%"submit%" value=%"Upload%"/>%N</form>")
|
||||
page.send_to (res)
|
||||
else
|
||||
create l_body.make (255)
|
||||
l_body.append ("<h1>EWF: Uploaded files</h1>%N")
|
||||
l_body.append ("<ul>")
|
||||
across
|
||||
req.uploaded_files as c
|
||||
loop
|
||||
l_body.append ("<li>")
|
||||
l_body.append ("<div>" + c.item.name + "=" + html_encode (c.item.filename) + " size=" + c.item.size.out + " type=" + c.item.content_type + "</div>")
|
||||
create fn.make_from_string (files_root)
|
||||
l_safe_filename := c.item.safe_filename
|
||||
fn.set_file_name (l_safe_filename)
|
||||
if c.item.move_to (fn.string) then
|
||||
if c.item.content_type.starts_with ("image") then
|
||||
l_body.append ("%N<a href=%"../files/" + url_encode (l_safe_filename) + "%"><img src=%"../files/"+ l_safe_filename +"%" /></a>")
|
||||
else
|
||||
l_body.append ("File " + html_encode (c.item.filename) + " is not a supported image<br/>%N")
|
||||
end
|
||||
end
|
||||
l_body.append ("</li>")
|
||||
end
|
||||
l_body.append ("</ul>")
|
||||
|
||||
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
|
||||
31
examples/upload_image/upload_image-safe.ecf
Normal file
31
examples/upload_image/upload_image-safe.ecf
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="upload_image" uuid="F2400BE8-D8EB-48EB-B4E4-5D4377062A7F">
|
||||
<target name="upload_image">
|
||||
<root class="IMAGE_UPLOADER" feature="make"/>
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/\.git$</exclude>
|
||||
<exclude>/\.svn$</exclude>
|
||||
</file_rule>
|
||||
<option debug="true" warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
|
||||
<debug name="nino" enabled="true"/>
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="connector_nino" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf" readonly="false" use_application_options="true">
|
||||
<option>
|
||||
<assertions precondition="true" check="true" invariant="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
</library>
|
||||
<library name="default_nino" location="..\..\library\server\wsf\default\nino-safe.ecf" readonly="false" use_application_options="true"/>
|
||||
<library name="encoder" location="..\..\library\text\encoder\encoder-safe.ecf" readonly="false"/>
|
||||
<library name="http" location="..\..\library\protocol\http\http-safe.ecf" readonly="false"/>
|
||||
<library name="router" location="..\..\library\server\request\router\router-safe.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="uri_template" location="..\..\library\protocol\uri_template\uri_template-safe.ecf" readonly="false"/>
|
||||
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf" readonly="false" use_application_options="true"/>
|
||||
<cluster name="src" location="src\" recursive="true">
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,6 +185,9 @@ feature -- Execution
|
||||
h: HTTP_HEADER
|
||||
s: STRING_8
|
||||
do
|
||||
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
|
||||
@@ -178,12 +198,16 @@ feature -- Execution
|
||||
res.put_string (s)
|
||||
res.flush
|
||||
end
|
||||
end
|
||||
|
||||
respond_access_denied (uri: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||
local
|
||||
h: HTTP_HEADER
|
||||
s: STRING_8
|
||||
do
|
||||
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
|
||||
@@ -194,6 +218,7 @@ feature -- Execution
|
||||
res.put_string (s)
|
||||
res.flush
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ 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
|
||||
|
||||
@@ -32,6 +33,8 @@ feature -- Access
|
||||
name: READABLE_STRING_32
|
||||
-- Parameter name
|
||||
|
||||
url_encoded_name: READABLE_STRING_8
|
||||
|
||||
first_value: detachable WSF_VALUE
|
||||
-- First value if any.
|
||||
do
|
||||
@@ -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
|
||||
|
||||
217
library/server/wsf/src/request/value/wsf_uploaded_file.e
Normal file
217
library/server/wsf/src/request/value/wsf_uploaded_file.e
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
171
library/server/wsf/src/response/wsf_html_page_response.e
Normal file
171
library/server/wsf/src/response/wsf_html_page_response.e
Normal file
@@ -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 := "<!DOCTYPE html PUBLIC %"-//W3C//DTD XHTML 1.0 Strict//EN%" %"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd%">"
|
||||
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 := "<meta name=%"" + a_name + "%" content=%"" + a_content + "%" />"
|
||||
head_lines.extend (s)
|
||||
end
|
||||
|
||||
add_meta_http_equiv (a_http_equiv: STRING; a_content: STRING)
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
s := "<meta http-equiv=%"" + a_http_equiv + "%" content=%"" + a_content + "%" />"
|
||||
head_lines.extend (s)
|
||||
end
|
||||
|
||||
add_style (a_href: STRING; a_media: detachable STRING)
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
s := "<link rel=%"stylesheet%" href=%""+ a_href + "%" type=%"text/css%""
|
||||
if a_media /= Void then
|
||||
s.append (" media=%""+ a_media + "%"")
|
||||
end
|
||||
s.append ("/>")
|
||||
head_lines.extend (s)
|
||||
end
|
||||
|
||||
add_javascript_url (a_src: STRING)
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
s := "<script type=%"text/javascript%" src=%"" + a_src + "%"></script>"
|
||||
head_lines.extend (s)
|
||||
end
|
||||
|
||||
add_javascript_content (a_script: STRING)
|
||||
local
|
||||
s: STRING_8
|
||||
do
|
||||
s := "<script type=%"text/javascript%">%N" + a_script + "%N</script>"
|
||||
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 ("<html xmlns=%"http://www.w3.org/1999/xhtml%"")
|
||||
if attached language as lang then
|
||||
s.append (" xml:lang=%""+ lang +"%" lang=%""+ lang +"%"")
|
||||
end
|
||||
s.append (">%N")
|
||||
|
||||
t := title
|
||||
lines := head_lines
|
||||
if t /= Void or else lines.count > 0 then
|
||||
s.append ("<head>")
|
||||
if t /= Void then
|
||||
s.append ("<title>" + t + "</title>%N")
|
||||
end
|
||||
s.append_character ('%N')
|
||||
across
|
||||
lines as l
|
||||
loop
|
||||
s.append (l.item)
|
||||
s.append_character ('%N')
|
||||
end
|
||||
s.append ("</head>%N")
|
||||
end
|
||||
|
||||
b := body
|
||||
s.append ("<body>%N")
|
||||
if b /= Void then
|
||||
s.append (b)
|
||||
end
|
||||
s.append ("%N</body></html>%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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user