diff --git a/examples/tutorial/step_4/hello/src/user_message_handler.e b/examples/tutorial/step_4/hello/src/user_message_handler.e
index 12a6a0e8..5e1b3f5e 100644
--- a/examples/tutorial/step_4/hello/src/user_message_handler.e
+++ b/examples/tutorial/step_4/hello/src/user_message_handler.e
@@ -10,6 +10,10 @@ class
inherit
WSF_URI_TEMPLATE_RESPONSE_HANDLER
+ SHARED_WSF_PERCENT_ENCODER
+ rename
+ percent_encoder as url_encoder
+ end
feature -- Access
@@ -75,7 +79,8 @@ feature -- Access
url_encoded_string (s: READABLE_STRING_32): STRING_8
do
- Result := (create {UTF8_URL_ENCODER}).encoded_string (s)
+ create Result.make (s.count)
+ url_encoder.append_percent_encoded_string_to (s, Result)
end
html_decoded_string (v: READABLE_STRING_32): READABLE_STRING_32
diff --git a/library/network/protocol/http/src/http_file_extension_mime_mapping.e b/library/network/protocol/http/src/http_file_extension_mime_mapping.e
index 387e8ed4..043e0fc1 100644
--- a/library/network/protocol/http/src/http_file_extension_mime_mapping.e
+++ b/library/network/protocol/http/src/http_file_extension_mime_mapping.e
@@ -33,8 +33,7 @@ feature {NONE} -- Initialization
-- Create with no mapping
-- but one can use `map' to add new mapping
do
- create mapping.make (n)
- mapping.compare_objects
+ create mapping.make_caseless (n)
end
make_default
@@ -43,9 +42,8 @@ feature {NONE} -- Initialization
local
m: like mapping
do
- create m.make (40)
+ create m.make_caseless (40)
mapping := m
- m.compare_objects
m.force (text_css, "css")
m.force (text_html, "html")
m.force (text_xml, "xml")
@@ -74,13 +72,13 @@ feature {NONE} -- Initialization
m.force (text_plain, "txt")
end
- make_from_file (fn: READABLE_STRING_8)
+ make_from_file (fn: READABLE_STRING_GENERAL)
-- Create with mime.types file
-- One can use `map' to add new mapping
local
f: RAW_FILE
do
- create f.make (fn)
+ create f.make_with_name (fn)
if f.exists and then f.is_readable then
make_empty (50)
f.open_read
@@ -128,7 +126,7 @@ feature {NONE} -- Initialization
feature -- Access
- mime_type (ext: READABLE_STRING_8): detachable READABLE_STRING_8
+ mime_type (ext: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- Mime type for extension `ext'
do
Result := mapping.item (ext.as_lower)
@@ -136,7 +134,7 @@ feature -- Access
feature -- Element change
- map (e: READABLE_STRING_8; t: READABLE_STRING_8)
+ map (e: READABLE_STRING_GENERAL; t: READABLE_STRING_8)
-- Add mapping extension `e' to mime type `t'
do
mapping.force (t, e.as_lower)
@@ -220,13 +218,13 @@ feature {NONE} -- Implementation
feature {NONE} -- Extension MIME mapping
- mapping: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
+ mapping: STRING_TABLE [READABLE_STRING_8]
invariant
mapping_keys_are_lowercase: across mapping as c all c.key.same_string (c.key.as_lower) end
note
- copyright: "2011-2011, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e
index 21d4bfc4..acd21662 100644
--- a/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e
+++ b/library/server/wsf/router/documentation/wsf_router_self_documentation_message.e
@@ -137,7 +137,7 @@ feature {WSF_RESPONSE} -- Output
debug
l_description.append ("
Meta Information
")
- l_description.append ("- PATH_INFO=" + request.path_info + "
")
+ l_description.append ("- PATH_INFO=" + request.percent_encoded_path_info + "
")
l_description.append ("- QUERY_STRING=" + request.query_string + "
")
l_description.append ("- REQUEST_URI=" + request.request_uri + "
")
l_description.append ("- SCRIPT_NAME=" + request.script_name + "
")
diff --git a/library/server/wsf/router/support/starts_with/wsf_starts_with_handler.e b/library/server/wsf/router/support/starts_with/wsf_starts_with_handler.e
index b1d6d422..b3863683 100644
--- a/library/server/wsf/router/support/starts_with/wsf_starts_with_handler.e
+++ b/library/server/wsf/router/support/starts_with/wsf_starts_with_handler.e
@@ -20,7 +20,7 @@ feature -- Execution
a_start_path_attached: a_start_path /= Void
req_attached: req /= Void
res_attached: res /= Void
- path_start_with_a_start_path: req.path_info.starts_with (a_start_path)
+ path_start_with_a_start_path: req.percent_encoded_path_info.starts_with (a_start_path)
deferred
end
@@ -33,7 +33,7 @@ feature {WSF_ROUTER} -- Mapping
end
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e
index ac09d22c..1a1a8435 100644
--- a/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e
+++ b/library/server/wsf/router/support/starts_with/wsf_starts_with_mapping_i.e
@@ -83,7 +83,7 @@ feature {NONE} -- Execution
a_start_path_attached: a_start_path /= Void
req_attached: req /= Void
res_attached: res /= Void
- path_start_with_a_start_path: req.path_info.starts_with (a_start_path)
+ path_start_with_a_start_path: req.percent_encoded_path_info.starts_with (a_start_path)
deferred
end
diff --git a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e
index f1430fa0..786d2af6 100644
--- a/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e
+++ b/library/server/wsf/router/support/uri_template/wsf_uri_template_mapping_i.e
@@ -61,7 +61,7 @@ feature -- Status
--
local
tpl: URI_TEMPLATE
- p: READABLE_STRING_32
+ p: READABLE_STRING_8
do
p := path_from_request (req)
tpl := based_uri_template (template, a_router)
@@ -72,7 +72,7 @@ feature -- Status
--
local
tpl: URI_TEMPLATE
- p: READABLE_STRING_32
+ p: READABLE_STRING_8
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
do
p := path_from_request (req)
diff --git a/library/server/wsf/router/wsf_file_system_handler.e b/library/server/wsf/router/wsf_file_system_handler.e
index 9e54a43e..f494b5b4 100644
--- a/library/server/wsf/router/wsf_file_system_handler.e
+++ b/library/server/wsf/router/wsf_file_system_handler.e
@@ -15,31 +15,53 @@ inherit
WSF_SELF_DOCUMENTED_HANDLER
+ SHARED_HTML_ENCODER
+
+ SHARED_WSF_PERCENT_ENCODER
+ rename
+ percent_encoder as url_encoder
+ export
+ {NONE} all
+ end
+
+ SHARED_EXECUTION_ENVIRONMENT
+ export
+ {NONE} all
+ end
+
create
+ make_with_path,
+ make_hidden_with_path,
make,
make_hidden
feature {NONE} -- Initialization
- make (d: like document_root)
- require
- valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
- local
- e: EXECUTION_ENVIRONMENT
+ make_with_path (d: like document_root)
do
if d.is_empty then
- create e
- document_root := e.current_working_directory
+ document_root := execution_environment.current_working_path
else
document_root := d
end
ensure
- not document_root.is_empty and then not document_root.ends_with (operating_environment.directory_separator.out)
+ not document_root.is_empty
end
- make_hidden (d: like document_root)
- require
- valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
+ make_hidden_with_path (d: like document_root)
+ do
+ make_with_path (d)
+ is_hidden := True
+ ensure
+ hidden: is_hidden
+ end
+
+ make (d: READABLE_STRING_GENERAL)
+ do
+ make_with_path (create {PATH}.make_from_string (d))
+ end
+
+ make_hidden (d: READABLE_STRING_GENERAL)
do
make (d)
is_hidden := True
@@ -60,9 +82,10 @@ feature -- Documentation
Result.add_description ("File service")
end
-feature -- Access
+feature -- Access
+
+ document_root: PATH
- document_root: STRING
max_age: INTEGER
index_disabled: BOOLEAN
@@ -118,10 +141,10 @@ feature -- Execution
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
- p: STRING
+ p: STRING_32
do
- p := req.path_info
- if p.starts_with (a_start_path) then
+ create p.make_from_string (req.path_info)
+ if p.starts_with_general (a_start_path) then
p.remove_head (a_start_path.count)
else
check starts_with_base: False end
@@ -131,16 +154,16 @@ feature -- Execution
execute_starts_with (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
do
- execute (a_start_path,req, res)
+ execute (a_start_path, req, res)
end
- process_uri (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_uri (uri: READABLE_STRING_32; req: WSF_REQUEST; res: WSF_RESPONSE)
local
f: RAW_FILE
- fn: READABLE_STRING_8
+ fn: like resource_filename
do
fn := resource_filename (uri)
- create f.make (fn)
+ create f.make_with_path (fn)
if f.exists then
if f.is_readable then
if f.is_directory then
@@ -160,14 +183,15 @@ feature -- Execution
end
end
- process_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
+ process_index (a_uri: READABLE_STRING_8; dn: PATH; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
uri, s: STRING_8
d: DIRECTORY
- l_files: LIST [STRING_8]
+ l_files: LIST [PATH]
do
- create d.make_open_read (dn)
+ create d.make_with_path (dn)
+ d.open_read
if attached directory_index_file (d) as f then
process_file (f, req, res)
else
@@ -187,12 +211,16 @@ feature -- Execution
s.replace_substring_all ("$URI", uri)
from
- l_files := d.linear_representation
+ l_files := d.entries
l_files.start
until
l_files.after
loop
- s.append ("- " + l_files.item_for_iteration + "
%N")
+ s.append ("- ")
+ s.append (html_encoder.encoded_string (l_files.item.name))
+ s.append ("
%N")
l_files.forth
end
s.append ("[
@@ -217,12 +245,12 @@ feature -- Execution
process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
local
- ext: READABLE_STRING_8
+ ext: READABLE_STRING_32
ct: detachable READABLE_STRING_8
fres: WSF_FILE_RESPONSE
dt: DATE_TIME
do
- ext := extension (f.name)
+ ext := extension (f.path.name)
ct := extension_mime_mapping.mime_type (ext)
if ct = Void then
ct := {HTTP_MIME_TYPES}.application_force_download
@@ -235,7 +263,7 @@ feature -- Execution
then
process_not_modified (f_date, req, res)
else
- create fres.make_with_content_type (ct, f.name)
+ create fres.make_with_content_type (ct, f.path.name)
fres.set_status_code ({HTTP_STATUS_CODE}.ok)
-- cache control
@@ -341,7 +369,7 @@ feature {NONE} -- Implementation
directory_index_file (d: DIRECTORY): detachable FILE
local
f: detachable RAW_FILE
- fn: FILE_NAME
+ fn: PATH
do
if attached directory_index as default_index then
across
@@ -350,12 +378,11 @@ feature {NONE} -- Implementation
Result /= Void
loop
if d.has_entry (c.item) then
- create fn.make_from_string (d.name)
- fn.set_file_name (c.item)
+ fn := d.path.extended (c.item)
if f = Void then
- create f.make (fn.string)
+ create f.make_with_path (fn)
else
- f.make (fn.string)
+ f.make_with_path (fn)
end
if f.exists and then f.is_readable then
Result := f
@@ -365,28 +392,34 @@ feature {NONE} -- Implementation
end
end
- resource_filename (uri: READABLE_STRING_8): READABLE_STRING_8
- do
- Result := real_filename (document_root + operating_environment.directory_separator.out + real_filename (uri))
- end
-
- dirname (uri: READABLE_STRING_8): READABLE_STRING_8
+ resource_filename (uri: READABLE_STRING_32): PATH
local
- p: INTEGER
+ s: like uri_path_to_filename
do
- p := uri.last_index_of ('/', uri.count)
- if p > 0 then
- Result := uri.substring (1, p - 1)
- else
- create {STRING_8} Result.make_empty
+ Result := document_root
+ s := uri_path_to_filename (uri)
+ if not s.is_empty then
+ Result := Result.extended (s)
end
end
- filename (uri: READABLE_STRING_8): READABLE_STRING_8
+ dirname (uri: READABLE_STRING_32): READABLE_STRING_32
local
p: INTEGER
do
- p := uri.last_index_of ('/', uri.count)
+ p := uri.last_index_of ({CHARACTER_32} '/', uri.count)
+ if p > 0 then
+ Result := uri.substring (1, p - 1)
+ else
+ create {STRING_32} Result.make_empty
+ end
+ end
+
+ filename (uri: READABLE_STRING_32): READABLE_STRING_32
+ local
+ p: INTEGER
+ do
+ p := uri.last_index_of ({CHARACTER_32} '/', uri.count)
if p > 0 then
Result := uri.substring (p + 1, uri.count)
else
@@ -394,58 +427,52 @@ feature {NONE} -- Implementation
end
end
- extension (uri: READABLE_STRING_8): READABLE_STRING_8
+ extension (uri: READABLE_STRING_32): READABLE_STRING_32
local
p: INTEGER
do
- p := uri.last_index_of ('.', uri.count)
+ p := uri.last_index_of ({CHARACTER_32} '.', uri.count)
if p > 0 then
Result := uri.substring (p + 1, uri.count)
else
- create {STRING_8} Result.make_empty
+ create {STRING_32} Result.make_empty
end
end
- real_filename (fn: STRING): STRING
+ uri_path_to_filename (fn: READABLE_STRING_32): STRING_32
-- Real filename from url-path `fn'
--| Find a better design for this piece of code
--| Eventually in a spec/$ISE_PLATFORM/ specific cluster
+ local
+ n: INTEGER
do
- if fn.is_empty then
- Result := fn
- else
+ n := fn.count
+ create Result.make_from_string (fn)
+ if n > 0 and then Result.item (Result.count) = {CHARACTER_32} '/' then
+ Result.remove_tail (1)
+ n := n - 1
+ end
+ if n > 0 and then Result.item (1) = {CHARACTER_32} '/' then
+ Result.remove_head (1)
+ n := n - 1
+ end
+
+ if n > 0 then
if {PLATFORM}.is_windows then
- create Result.make_from_string (fn)
- Result.replace_substring_all ("/", "\")
- if Result [Result.count] = '\' then
- Result.remove_tail (1)
- end
- else
- Result := fn
- if Result [Result.count] = '/' then
- Result.remove_tail (1)
- end
+ Result.replace_substring_all ({STRING_32} "/", {STRING_32} "\")
end
end
end
feature {NONE} -- Implementation
- node_exists (p: READABLE_STRING_8): BOOLEAN
- local
- f: RAW_FILE
- do
- create f.make (p)
- Result := f.exists
- end
-
extension_mime_mapping: HTTP_FILE_EXTENSION_MIME_MAPPING
local
f: RAW_FILE
once
- create f.make ("mime.types")
+ create f.make_with_name ("mime.types")
if f.exists and then f.is_readable then
- create Result.make_from_file (f.name)
+ create Result.make_from_file (f.path.name)
else
create Result.make_default
end
diff --git a/library/server/wsf/router/wsf_router_mapping.e b/library/server/wsf/router/wsf_router_mapping.e
index 475818ca..873a25cb 100644
--- a/library/server/wsf/router/wsf_router_mapping.e
+++ b/library/server/wsf/router/wsf_router_mapping.e
@@ -77,12 +77,12 @@ feature -- Status
feature -- Helper
- path_from_request (req: WSF_REQUEST): READABLE_STRING_32
+ path_from_request (req: WSF_REQUEST): READABLE_STRING_8
-- Path used by `Current' to check that mapping matches request `req'
require
req_attached: req /= Void
do
- Result := req.path_info
+ Result := req.percent_encoded_path_info
ensure
path_from_request_attached: Result /= Void
end
diff --git a/library/server/wsf/session/wsf_cookie_session.e b/library/server/wsf/session/wsf_cookie_session.e
index 7c8d1425..0e499f6d 100644
--- a/library/server/wsf/session/wsf_cookie_session.e
+++ b/library/server/wsf/session/wsf_cookie_session.e
@@ -10,6 +10,11 @@ class
inherit
WSF_SESSION
+ SHARED_EXECUTION_ENVIRONMENT
+ export
+ {NONE} all
+ end
+
create
make,
make_new
@@ -128,15 +133,6 @@ feature {NONE} -- Storage
data.compare_objects
end
- sessions_folder_name: READABLE_STRING_8
- local
- dn: DIRECTORY_NAME
- once
- create dn.make_from_string ((create {EXECUTION_ENVIRONMENT}).current_working_directory)
- dn.extend ("_sessions_")
- Result := dn.string
- end
-
load
do
if manager.session_exists (uuid) then
@@ -181,7 +177,7 @@ feature {NONE} -- Implementation
end
note
- copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/session/wsf_fs_session_manager.e b/library/server/wsf/session/wsf_fs_session_manager.e
index 260607a1..81187b6f 100644
--- a/library/server/wsf/session/wsf_fs_session_manager.e
+++ b/library/server/wsf/session/wsf_fs_session_manager.e
@@ -21,12 +21,12 @@ feature {NONE} -- Initialization
make_with_folder ("_WSF_SESSIONS_")
end
- make_with_folder (a_folder: like sessions_folder_name)
+ make_with_folder (a_folder: READABLE_STRING_GENERAL)
do
- sessions_folder_name := a_folder
+ create sessions_folder_name.make_from_string (a_folder)
end
- sessions_folder_name: STRING_8
+ sessions_folder_name: PATH
feature -- Access
@@ -34,7 +34,7 @@ feature -- Access
local
f: RAW_FILE
do
- create f.make (file_name (a_session_uuid))
+ create f.make_with_path (file_name (a_session_uuid))
Result := f.exists and then f.is_readable
end
@@ -42,7 +42,7 @@ feature -- Access
local
f: RAW_FILE
do
- create f.make (file_name (a_session_uuid))
+ create f.make_with_path (file_name (a_session_uuid))
if f.exists and then f.is_readable then
f.open_read
if attached data_from_file (f) as d then
@@ -68,7 +68,7 @@ feature -- Persistence
delete_session (a_session)
else
ensure_session_folder_exists
- create f.make (file_name (a_session.uuid))
+ create f.make_with_path (file_name (a_session.uuid))
if not f.exists or else f.is_writable then
f.create_read_write
a_session.data.set_expiration (a_session.expiration)
@@ -91,7 +91,7 @@ feature -- Persistence
rescued: BOOLEAN
do
if not rescued then
- create f.make (file_name (a_session.uuid))
+ create f.make_with_path (file_name (a_session.uuid))
if f.exists then
f.delete
end
@@ -131,7 +131,7 @@ feature {NONE} -- Implementation
local
d: DIRECTORY
once
- create d.make (sessions_folder_name)
+ create d.make_with_path (sessions_folder_name)
if not d.exists then
d.recursive_create_dir
end
@@ -143,18 +143,13 @@ feature {NONE} -- Implementation
local
d: DIRECTORY
do
- create d.make (sessions_folder_name)
+ create d.make_with_path (sessions_folder_name)
Result := d.exists and then d.is_writable
end
- file_name (a_uuid: like {WSF_SESSION}.uuid): READABLE_STRING_8
- local
- fn: FILE_NAME
+ file_name (a_uuid: like {WSF_SESSION}.uuid): PATH
do
- create fn.make_from_string (sessions_folder_name)
- fn.set_file_name (a_uuid.out)
- fn.add_extension ("session")
- Result := fn.string
+ Result := sessions_folder_name.extended (a_uuid.out).appended_with_extension ("session")
end
note
diff --git a/library/server/wsf/src/implementation/shared_wsf_percent_encoder.e b/library/server/wsf/src/implementation/shared_wsf_percent_encoder.e
new file mode 100644
index 00000000..9d00bd44
--- /dev/null
+++ b/library/server/wsf/src/implementation/shared_wsf_percent_encoder.e
@@ -0,0 +1,28 @@
+note
+ description: "Objects to access the shared once WSF_PERCENT_ENCODER ..."
+ date: "$Date$"
+ revision: "$Revision$"
+
+class
+ SHARED_WSF_PERCENT_ENCODER
+
+feature -- Encoder
+
+ percent_encoder: WSF_PERCENT_ENCODER
+ -- Shared Percent encoding engine.
+ once
+ create Result
+ end
+
+note
+ copyright: "2011-2013, 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/wsf/src/implementation/wsf_percent_encoder.e b/library/server/wsf/src/implementation/wsf_percent_encoder.e
new file mode 100644
index 00000000..8d60b89a
--- /dev/null
+++ b/library/server/wsf/src/implementation/wsf_percent_encoder.e
@@ -0,0 +1,523 @@
+note
+ description: "[
+ Component to handle percent encoding
+ ]"
+ date: "$Date: 2013-05-21 01:15:17 +0200 (mar., 21 mai 2013) $"
+ revision: "$Revision: 92557 $"
+ EIS: "name=Percent-encoding", "protocol=URI", "src=http://en.wikipedia.org/wiki/Percent-encoding"
+
+class
+ WSF_PERCENT_ENCODER
+
+feature -- Percent encoding
+
+ percent_encoded_string (v: READABLE_STRING_GENERAL): STRING_8
+ -- Return `a_string' percent-encoded
+ do
+ create Result.make (v.count)
+ append_percent_encoded_string_to (v, Result)
+ end
+
+ append_percent_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
+ -- Append `a_string' as percent-encoded value to `a_result'
+ local
+ c: NATURAL_32
+ i,n: INTEGER
+ do
+ from
+ i := 1
+ n := s.count
+ until
+ i > n
+ loop
+ c := s.code (i)
+ if
+ --| unreserved ALPHA / DIGIT
+ (48 <= c and c <= 57) -- DIGIT: 0 .. 9
+ or (65 <= c and c <= 90) -- ALPHA: A .. Z
+ or (97 <= c and c <= 122) -- ALPHA: a .. z
+ then
+ a_result.append_code (c)
+ else
+ inspect c
+ when
+ 45, 46, 95, 126 -- unreserved characters: -._~
+ then
+ a_result.append_code (c)
+ when
+ 58, 64, -- reserved =+ gen-delims: :@
+ 33, 36, 38, 39, 40, 41, 42, -- reserved =+ sub-delims: !$&'()*
+ 43, 44, 59, 61, -- reserved = sub-delims: +,;=
+ 37 -- percent encoding: %
+ then
+ append_percent_encoded_character_code_to (c, a_result)
+ else
+ append_percent_encoded_character_code_to (c, a_result)
+ end
+ end
+ i := i + 1
+ end
+ end
+
+feature -- Percent encoding: character
+
+ append_percent_encoded_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
+ -- Append character code `a_code' as percent-encoded content into `a_result'
+ do
+ if a_code > 0xFF then
+ -- Unicode
+ append_percent_encoded_unicode_character_code_to (a_code, a_result)
+ elseif a_code > 0x7F then
+ -- Extended ASCII
+ -- This requires percent-encoding on UTF-8 converted character.
+ append_percent_encoded_unicode_character_code_to (a_code, a_result)
+ else
+ -- ASCII
+ append_percent_encoded_ascii_character_code_to (a_code, a_result)
+ end
+ ensure
+ appended: a_result.count > old a_result.count
+ end
+
+feature {NONE} -- Implementation: character encoding
+
+ append_percent_encoded_ascii_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
+ -- Append extended ascii character code `a_code' as percent-encoded content into `a_result'
+ -- Note: it does not UTF-8 convert this extended ASCII.
+ require
+ is_extended_ascii: a_code <= 0xFF
+ local
+ c: INTEGER
+ do
+ if a_code > 0xFF then
+ -- Unicode
+ append_percent_encoded_unicode_character_code_to (a_code, a_result)
+ else
+ -- Extended ASCII
+ c := a_code.to_integer_32
+ a_result.append_code (37) -- 37 '%%'
+ a_result.append_code (hex_digit [c |>> 4])
+ a_result.append_code (hex_digit [c & 0xF])
+ end
+ ensure
+ appended: a_result.count > old a_result.count
+ end
+
+ append_percent_encoded_unicode_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
+ -- Append Unicode character code `a_code' as UTF-8 and percent-encoded content into `a_result'
+ -- Note: it does include UTF-8 conversion of extended ASCII and Unicode.
+ do
+ if a_code <= 0x7F then
+ -- 0xxxxxxx
+ append_percent_encoded_ascii_character_code_to (a_code, a_result)
+ elseif a_code <= 0x7FF then
+ -- 110xxxxx 10xxxxxx
+ append_percent_encoded_ascii_character_code_to ((a_code |>> 6) | 0xC0, a_result)
+ append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
+ elseif a_code <= 0xFFFF then
+ -- 1110xxxx 10xxxxxx 10xxxxxx
+ append_percent_encoded_ascii_character_code_to ((a_code |>> 12) | 0xE0, a_result)
+ append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
+ append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
+ else
+ -- c <= 1FFFFF - there are no higher code points
+ -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ append_percent_encoded_ascii_character_code_to ((a_code |>> 18) | 0xF0, a_result)
+ append_percent_encoded_ascii_character_code_to (((a_code |>> 12) & 0x3F) | 0x80, a_result)
+ append_percent_encoded_ascii_character_code_to (((a_code |>> 6) & 0x3F) | 0x80, a_result)
+ append_percent_encoded_ascii_character_code_to ((a_code & 0x3F) | 0x80, a_result)
+ end
+ ensure
+ appended: a_result.count > old a_result.count
+ end
+
+feature -- Percent decoding
+
+ percent_decoded_string (v: READABLE_STRING_GENERAL): STRING_32
+ -- Return the percent decoded string equivalent to the percent-encoded string `v'
+ --| Note that is `a_result' is a STRING_8, any Unicode character will be kept as UTF-8
+ do
+ create Result.make (v.count)
+ append_percent_decoded_string_to (v, Result)
+ end
+
+ append_percent_decoded_string_to (v: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
+ -- Append to `a_result' a string equivalent to the percent-encoded string `v'
+ --| Note that is `a_result' is a STRING_8, any Unicode character will be kept as UTF-8
+ local
+ i,n: INTEGER
+ c: NATURAL_32
+ pr: CELL [INTEGER]
+ a_result_is_string_32: BOOLEAN
+ do
+ a_result_is_string_32 := attached {STRING_32} a_result
+ from
+ i := 1
+ create pr.put (i)
+ n := v.count
+ until
+ i > n
+ loop
+ c := v.code (i)
+ inspect c
+ when 43 then -- 43 '+'
+ -- Some implementation are replacing spaces with "+" instead of "%20"
+ a_result.append_code (32) -- 32 ' '
+ when 37 then -- 37 '%%'
+ -- An escaped character ?
+ if i = n then -- Error?
+ a_result.append_code (c)
+ else
+ if a_result_is_string_32 then
+ -- Convert UTF-8 to UTF-32
+ pr.replace (i)
+ c := next_percent_decoded_unicode_character_code (v, pr)
+ a_result.append_code (c)
+ i := pr.item
+ else
+ -- Keep UTF-8
+ pr.replace (i)
+ c := next_percent_decoded_character_code (v, pr)
+ a_result.append_code (c)
+ i := pr.item
+ end
+ end
+ else
+ if c <= 0x7F then
+ a_result.append_code (c)
+ else
+ if a_result_is_string_32 then
+ a_result.append_code (c)
+ else
+ append_percent_encoded_character_code_to (c, a_result)
+ end
+ end
+ end
+ i := i + 1
+ end
+ end
+
+feature {NONE} -- Implementation: decoding
+
+ next_percent_decoded_character_code (v: READABLE_STRING_GENERAL; a_position: CELL [INTEGER]): NATURAL_32
+ -- Character decoded from string `v' starting from index `a_position.item'
+ -- note: it also updates `a_position.item' to indicate the new index position.
+ require
+ valid_start: a_position.item <= v.count
+ is_percent_char: v.code (a_position.item) = 37 -- 37 '%%'
+ local
+ c: NATURAL_32
+ i, n: INTEGER
+ not_a_digit: BOOLEAN
+ ascii_pos: NATURAL_32
+ ival: NATURAL_32
+ pos: INTEGER
+ c_is_digit: BOOLEAN
+ do
+ --| pos is index in stream of escape character ('%')
+ pos := a_position.item
+ c := v.code (pos + 1)
+ if c = 85 or c = 117 then -- 117 'u' 85 'U'
+ -- NOTE: this is not a standard, but it can occur, so use this for decoding only
+ -- An escaped Unicode (ucs2) value, from ECMA scripts
+ -- has the form: %u where is the UCS value
+ -- of the character (two byte integer, one to 4 chars
+ -- after escape sequence).
+ -- See: http://en.wikipedia.org/wiki/Percent-encoding#Non-standard_implementations
+ -- UTF-8 result can be 1 to 4 characters.
+ from
+ i := pos + 2
+ n := v.count
+ until
+ (i > n) or not_a_digit
+ loop
+ c := v.code (i)
+ c_is_digit := (48 <= c and c <= 57) -- DIGIT: 0 .. 9
+ if
+ c_is_digit
+ or (97 <= c and c <= 102) -- ALPHA: a..f
+ or (65 <= c and c <= 70) -- ALPHA: A..F
+ then
+ ival := ival * 16
+ if c_is_digit then
+ ival := ival + (c - 48) -- 48 '0'
+ else
+ if c > 70 then -- a..f
+ ival := ival + (c - 97) + 10 -- 97 'a'
+ else -- A..F
+ ival := ival + (c - 65) + 10 -- 65 'A'
+ end
+ end
+ i := i + 1
+ else
+ not_a_digit := True
+ i := i - 1
+ end
+ end
+ a_position.replace (i)
+ Result := ival
+ else
+ -- ASCII char?
+ ascii_pos := hexadecimal_string_to_natural_32 (v.substring (pos + 1, pos + 2))
+ Result := ascii_pos
+ a_position.replace (pos + 2)
+ end
+ end
+
+ next_percent_decoded_unicode_character_code (v: READABLE_STRING_GENERAL; a_position: CELL [INTEGER]): NATURAL_32
+ -- Next decoded character from `v' at position `a_position.item'
+ -- note: it also updates `a_position' to indicate the new index position.
+ require
+ valid_start: a_position.item <= v.count
+ is_percent_char: v.code (a_position.item) = 37 -- 37 '%%'
+ local
+ n, j: INTEGER
+ c: NATURAL_32
+ c1, c2, c3, c4: NATURAL_32
+ pr: CELL [INTEGER]
+ do
+ create pr.put (a_position.item)
+ c1 := next_percent_decoded_character_code (v, pr)
+
+ j := pr.item
+ n := v.count
+
+ Result := c1
+ a_position.replace (j)
+
+ if c1 <= 0x7F then
+ -- 0xxxxxxx
+ Result := c1
+ elseif c1 <= 0xDF then
+ -- 110xxxxx 10xxxxxx
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c2 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+ Result := (
+ ((c1 & 0x1F) |<< 6) |
+ ( c2 & 0x3F )
+ )
+ a_position.replace (j)
+ else
+ -- Do not try to decode
+ end
+ end
+ elseif c1 <= 0xEF then
+ -- 1110xxxx 10xxxxxx 10xxxxxx
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c2 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c3 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+
+ Result := (
+ ((c1 & 0xF) |<< 12) |
+ ((c2 & 0x3F) |<< 6) |
+ ( c3 & 0x3F )
+ )
+ a_position.replace (j)
+ else
+ -- Do not try to decode
+ end
+ end
+ else
+ -- Do not try to decode
+ end
+ end
+ elseif c1 <= 0xF7 then
+ -- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c2 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c3 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+ if j + 2 <= n then
+ c := v.code (j + 1)
+ if c = 37 then -- 37 '%%'
+ pr.replace (j + 1)
+ c4 := next_percent_decoded_character_code (v, pr)
+ j := pr.item
+
+ a_position.replace (j)
+
+ Result := (
+ ((c1 & 0x7) |<< 18 ) |
+ ((c2 & 0x3F) |<< 12) |
+ ((c3 & 0x3F) |<< 6) |
+ ( c4 & 0x3F )
+ )
+ else
+ -- Do not try to decode
+ end
+ end
+ else
+ -- Do not try to decode
+ end
+ end
+ else
+ -- Do not try to decode
+ end
+ end
+ else
+ Result := c1
+ end
+ end
+
+feature -- RFC and characters
+
+ is_hexa_decimal_character (c: CHARACTER_32): BOOLEAN
+ -- Is hexadecimal character ?
+ do
+ Result := ('a' <= c and c <= 'f') or ('A' <= c and c <= 'F') -- HEXA
+ or ('0' <= c and c <= '9') -- DIGIT
+ end
+
+ is_alpha_or_digit_character (c: CHARACTER_32): BOOLEAN
+ -- Is ALPHA or DIGIT character ?
+ do
+ Result := ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z') -- ALPHA
+ or ('0' <= c and c <= '9') -- DIGIT
+ end
+
+ is_alpha_character (c: CHARACTER_32): BOOLEAN
+ -- Is ALPHA character ?
+ do
+ Result := ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z')
+ end
+
+ is_digit_character (c: CHARACTER_32): BOOLEAN
+ -- Is DIGIT character ?
+ do
+ Result := ('0' <= c and c <= '9')
+ end
+
+ is_unreserved_character (c: CHARACTER_32): BOOLEAN
+ -- unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
+ do
+ if
+ ('a' <= c and c <= 'z') -- ALPHA
+ or ('A' <= c and c <= 'Z') -- ALPHA
+ or ('0' <= c and c <= '9') -- DIGIT
+ then
+ Result := True
+ else
+ inspect c
+ when '-', '_', '.', '~' then -- unreserved
+ Result := True
+ else
+ end
+ end
+ end
+
+ is_reserved_character (c: CHARACTER_32): BOOLEAN
+ -- reserved = gen-delims / sub-delims
+ do
+ Result := is_gen_delims_character (c) or is_sub_delims_character (c)
+ end
+
+ is_gen_delims_character (c: CHARACTER_32): BOOLEAN
+ -- gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
+ do
+ inspect c
+ when ':' , '/', '?' , '#' , '[' , ']' , '@' then
+ Result := True
+ else
+ end
+ end
+
+ is_sub_delims_character (c: CHARACTER_32): BOOLEAN
+ -- sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
+ -- / "*" / "+" / "," / ";" / "="
+ do
+ inspect c
+ when '!' , '$' , '&' , '%'' , '(' , ')' , '*' , '+' , ',' , ';' , '=' then -- sub-delims
+ Result := True
+ else
+ end
+ end
+
+feature {NONE} -- Implementation
+
+ hex_digit: SPECIAL [NATURAL_32]
+ -- Hexadecimal digits.
+ once
+ create Result.make_filled (0, 16)
+ Result [0] := {NATURAL_32} 48 -- 48 '0'
+ Result [1] := {NATURAL_32} 49 -- 49 '1'
+ Result [2] := {NATURAL_32} 50 -- 50 '2'
+ Result [3] := {NATURAL_32} 51 -- 51 '3'
+ Result [4] := {NATURAL_32} 52 -- 52 '4'
+ Result [5] := {NATURAL_32} 53 -- 53 '5'
+ Result [6] := {NATURAL_32} 54 -- 54 '6'
+ Result [7] := {NATURAL_32} 55 -- 55 '7'
+ Result [8] := {NATURAL_32} 56 -- 56 '8'
+ Result [9] := {NATURAL_32} 57 -- 57 '9'
+ Result [10] := {NATURAL_32} 65 -- 65 'A'
+ Result [11] := {NATURAL_32} 66 -- 66 'B'
+ Result [12] := {NATURAL_32} 67 -- 67 'C'
+ Result [13] := {NATURAL_32} 68 -- 68 'D'
+ Result [14] := {NATURAL_32} 69 -- 69 'E'
+ Result [15] := {NATURAL_32} 70 -- 70 'F'
+ end
+
+ is_hexa_decimal (a_string: READABLE_STRING_GENERAL): BOOLEAN
+ -- Is `a_string' a valid hexadecimal sequence?
+ local
+ l_convertor: like ctoi_convertor
+ do
+ l_convertor := ctoi_convertor
+ l_convertor.parse_string_with_type (a_string, {NUMERIC_INFORMATION}.type_natural_32)
+ Result := l_convertor.is_integral_integer
+ end
+
+ hexadecimal_string_to_natural_32 (a_hex_string: READABLE_STRING_GENERAL): NATURAL_32
+ -- Convert hexadecimal value `a_hex_string' to its corresponding NATURAL_32 value.
+ require
+ is_hexa: is_hexa_decimal (a_hex_string)
+ local
+ l_convertor: like ctoi_convertor
+ do
+ l_convertor := ctoi_convertor
+ l_convertor.parse_string_with_type (a_hex_string, {NUMERIC_INFORMATION}.type_no_limitation)
+ Result := l_convertor.parsed_natural_32
+ end
+
+ ctoi_convertor: HEXADECIMAL_STRING_TO_INTEGER_CONVERTER
+ -- Converter used to convert string to integer or natural.
+ once
+ create Result.make
+ Result.set_leading_separators_acceptable (False)
+ Result.set_trailing_separators_acceptable (False)
+ ensure
+ ctoi_convertor_not_void: Result /= Void
+ end
+
+note
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, 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/wsf/src/request/value/wsf_multiple_string.e b/library/server/wsf/src/request/value/wsf_multiple_string.e
index c4d6ab08..69cf8ebe 100644
--- a/library/server/wsf/src/request/value/wsf_multiple_string.e
+++ b/library/server/wsf/src/request/value/wsf_multiple_string.e
@@ -62,7 +62,7 @@ feature -- Access
url_encoded_name: READABLE_STRING_8
-- URL encoded string of `name'.
do
- Result := url_encoder.encoded_string (name)
+ Result := url_encoded_string (name)
end
values: LIST [WSF_STRING]
diff --git a/library/server/wsf/src/request/value/wsf_string.e b/library/server/wsf/src/request/value/wsf_string.e
index c51c3583..0da28891 100644
--- a/library/server/wsf/src/request/value/wsf_string.e
+++ b/library/server/wsf/src/request/value/wsf_string.e
@@ -50,20 +50,6 @@ feature -- Access
url_encoded_value: READABLE_STRING_8
-- URL encoded string of `value'.
- frozen string: like value
- obsolete
- "Use value [2012-May-31]"
- do
- Result := value
- end
-
- frozen url_encoded_string: like url_encoded_value
- obsolete
- "Use url_encoded_value [2012-May-31]"
- do
- Result := url_encoded_value
- end
-
feature -- Conversion
integer_value: INTEGER
@@ -137,7 +123,7 @@ feature -- Visitor
end
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/src/request/value/wsf_uploaded_file.e b/library/server/wsf/src/request/value/wsf_uploaded_file.e
index 98912d5a..b194f9b0 100644
--- a/library/server/wsf/src/request/value/wsf_uploaded_file.e
+++ b/library/server/wsf/src/request/value/wsf_uploaded_file.e
@@ -36,17 +36,17 @@ feature -- Access
feature -- Status report
- debug_output: STRING
+ debug_output: STRING_32
-- String that should be displayed in debugger to represent `Current'.
do
Result := Precursor
if
exists and then
- attached tmp_name as n
+ attached tmp_path as p
then
Result.append_character (' ')
Result.append_character ('%"')
- Result.append (n)
+ Result.append (p.name)
Result.append_character ('%"')
end
Result.append (" filename=%"")
@@ -108,9 +108,16 @@ feature -- Access: Uploaded File
size: INTEGER
-- Size of uploaded file
- tmp_name: detachable STRING
+ tmp_path: detachable PATH
-- Filename of tmp file
+ tmp_name: detachable READABLE_STRING_GENERAL
+ do
+ if attached tmp_path as p then
+ Result := p.name
+ end
+ end
+
tmp_basename: detachable STRING
-- Basename of tmp file
@@ -237,7 +244,7 @@ feature -- Implementation
feature -- Basic operation
- move_to (a_destination: STRING): BOOLEAN
+ move_to (a_destination: READABLE_STRING_GENERAL): BOOLEAN
-- Move current uploaded file to `a_destination'
--| Violates CQS principle.
require
@@ -246,10 +253,10 @@ feature -- Basic operation
local
f: RAW_FILE
do
- if attached tmp_name as n then
- create f.make (n)
+ if attached tmp_path as p then
+ create f.make_with_path (p)
if f.exists then
- f.change_name (a_destination)
+ f.rename_file (a_destination)
Result := True
end
end
@@ -274,8 +281,8 @@ feature -- Status
local
f: PLAIN_TEXT_FILE
do
- if attached tmp_name as n then
- create f.make (n)
+ if attached tmp_path as p then
+ create f.make_with_path (p)
Result := f.exists
end
end
@@ -288,10 +295,19 @@ feature -- Element change
error := e
end
+ set_tmp_path (p: like tmp_path)
+ do
+ tmp_path := p
+ end
+
set_tmp_name (n: like tmp_name)
-- Set `tmp_name' to `n'
do
- tmp_name := n
+ if n /= Void then
+ set_tmp_path (create {PATH}.make_from_string (n))
+ else
+ set_tmp_path (Void)
+ end
end
set_tmp_basename (n: like tmp_basename)
diff --git a/library/server/wsf/src/request/wsf_value.e b/library/server/wsf/src/request/wsf_value.e
index 5c42e804..6a1577e9 100644
--- a/library/server/wsf/src/request/wsf_value.e
+++ b/library/server/wsf/src/request/wsf_value.e
@@ -9,6 +9,13 @@ deferred class
inherit
DEBUG_OUTPUT
+ SHARED_WSF_PERCENT_ENCODER
+ rename
+ percent_encoder as url_encoder
+ export
+ {NONE} all
+ end
+
feature -- Access
name: READABLE_STRING_32
@@ -91,23 +98,26 @@ feature -- Helper
feature -- Status report
- debug_output: STRING
+ debug_output: STRING_32
-- String that should be displayed in debugger to represent `Current'.
do
- create Result.make_from_string (url_encoder.encoded_string (name) + "=" + url_encoder.encoded_string (string_representation))
+ create Result.make_from_string (name + {STRING_32} "=" + string_representation)
end
feature {NONE} -- Implementation
- url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32
+ url_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
-- Decoded url-encoded string `s'
do
- Result := url_encoder.decoded_string (s)
+ create Result.make (s.count)
+ url_encoder.append_percent_encoded_string_to (s, Result)
end
- url_encoder: URL_ENCODER
- once
- create {UTF8_URL_ENCODER} Result --| Chrome is UTF-8 encoding the non ascii in query
+ url_decoded_string (s: READABLE_STRING_GENERAL): STRING_32
+ -- Decoded url-encoded string `s'
+ do
+ create Result.make (s.count)
+ url_encoder.append_percent_decoded_string_to (s, Result)
end
feature -- Visitor
@@ -117,7 +127,7 @@ feature -- Visitor
end
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/src/response/wsf_download_response.e b/library/server/wsf/src/response/wsf_download_response.e
index cedc8a2a..2fbdc65d 100644
--- a/library/server/wsf/src/response/wsf_download_response.e
+++ b/library/server/wsf/src/response/wsf_download_response.e
@@ -10,6 +10,8 @@ class
inherit
WSF_RESPONSE_MESSAGE
+ SHARED_UTF8_URL_ENCODER
+
create
make,
make_with_content_type,
@@ -17,26 +19,26 @@ create
feature {NONE} -- Initialization
- make (a_file_name: READABLE_STRING_8)
+ make (a_file_name: READABLE_STRING_GENERAL)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
- file_name := a_file_name
- base_name := basename (a_file_name)
+ create file_path.make_from_string (a_file_name)
+ base_name := basename (file_path)
get_content_type
initialize
end
- make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
+ make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
set_status_code ({HTTP_STATUS_CODE}.ok)
- file_name := a_filename
- base_name := basename (a_filename)
+ create file_path.make_from_string (a_filename)
+ base_name := basename (file_path)
content_type := a_content_type
initialize
end
- make_html (a_filename: READABLE_STRING_8)
+ make_html (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
@@ -45,15 +47,14 @@ feature {NONE} -- Initialization
initialize
local
h: like header
- d: HTTP_DATE
do
create h.make
header := h
h.put_content_type (content_type)
h.put_transfer_encoding_binary
- h.put_content_length (filesize (file_name))
+ h.put_content_length (filesize (file_path))
h.put_content_disposition ("attachment", "filename=%""+ base_name +"%"")
- if attached filedate (file_name) as dt then
+ if attached filedate (file_path) as dt then
h.put_last_modified (dt)
end
end
@@ -89,7 +90,14 @@ feature -- Access
status_code: INTEGER assign set_status_code
+ file_path: PATH
+
file_name: READABLE_STRING_8
+ obsolete
+ "Use `file_path.name' for unicode support [2013-may]"
+ do
+ Result := file_path.utf_8_name
+ end
base_name: READABLE_STRING_8
@@ -125,73 +133,57 @@ feature {WSF_RESPONSE} -- Output
res.set_status_code (status_code)
res.put_header_text (header.string)
if not answer_head_request_method then
- send_file_content_to (file_name, res)
+ send_file_content_to (file_path, res)
end
end
feature {NONE} -- Implementation: file system helper
- filesize (fn: STRING): INTEGER
+ filesize (fn: PATH): INTEGER
-- Size of the file `fn'.
local
f: RAW_FILE
do
- create f.make (fn)
+ create f.make_with_path (fn)
if f.exists then
Result := f.count
end
end
- filedate (fn: STRING): detachable DATE_TIME
+ filedate (fn: PATH): detachable DATE_TIME
-- Size of the file `fn'.
local
f: RAW_FILE
d: HTTP_DATE
do
- create f.make (fn)
+ create f.make_with_path (fn)
if f.exists then
create d.make_from_timestamp (f.date)
Result := d.date_time
end
end
- file_extension (fn: STRING): STRING
+ file_extension (fn: PATH): STRING_32
-- Extension of file `fn'.
- local
- p: INTEGER
do
- p := fn.last_index_of ('.', fn.count)
- if p > 0 then
- Result := fn.substring (p + 1, fn.count)
+ if attached fn.extension as ext then
+ Result := ext
else
create Result.make_empty
end
end
- basename (fn: STRING): STRING
+ basename (fn: PATH): STRING
-- Basename of `fn'.
local
- p: INTEGER
+ s: READABLE_STRING_32
do
- p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
- if p > 0 then
- Result := fn.substring (p + 1, fn.count)
+ if attached fn.entry as p then
+ s := p.name
else
- Result := fn
- end
- end
-
- dirname (fn: STRING): STRING
- -- Dirname of `fn'.
- local
- p: INTEGER
- do
- p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
- if p > 0 then
- Result := fn.substring (1, p - 1)
- else
- create Result.make_empty
+ s := fn.name
end
+ Result := url_encoder.encoded_string (s)
end
feature -- Content-type related
@@ -203,7 +195,7 @@ feature -- Content-type related
m: detachable READABLE_STRING_8
do
create m_map.make_default
- m := m_map.mime_type (file_extension (file_name).as_lower)
+ m := m_map.mime_type (file_extension (file_path).as_lower)
if m = Void then
m := {HTTP_MIME_TYPES}.application_force_download
end
@@ -212,15 +204,15 @@ feature -- Content-type related
feature -- Implementation: output
- send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
+ send_file_content_to (fn: PATH; res: WSF_RESPONSE)
-- Send the content of file `fn'
require
string_not_empty: not fn.is_empty
- is_readable: (create {RAW_FILE}.make (fn)).is_readable
+ is_readable: (create {RAW_FILE}.make_with_path (fn)).is_readable
local
f: RAW_FILE
do
- create f.make (fn)
+ create f.make_with_path (fn)
check f.exists and then f.is_readable end
f.open_read
diff --git a/library/server/wsf/src/response/wsf_file_response.e b/library/server/wsf/src/response/wsf_file_response.e
index 8d00455b..28b21ff2 100644
--- a/library/server/wsf/src/response/wsf_file_response.e
+++ b/library/server/wsf/src/response/wsf_file_response.e
@@ -11,30 +11,49 @@ inherit
WSF_RESPONSE_MESSAGE
create
+ make_with_path,
+ make_with_content_type_and_path,
+ make_html_with_path,
make,
make_with_content_type,
make_html
feature {NONE} -- Initialization
- make (a_file_name: READABLE_STRING_8)
+ make_with_path (a_path: PATH)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
- file_name := a_file_name
+ file_path := a_path
get_content_type
initialize
end
- make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
- -- Initialize `Current'.
+ make_with_content_type_and_path (a_content_type: READABLE_STRING_8; a_path: PATH)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
- file_name := a_filename
+ file_path := a_path
content_type := a_content_type
initialize
end
- make_html (a_filename: READABLE_STRING_8)
+ make_html_with_path (a_path: PATH)
+ -- Initialize `Current'.
+ do
+ make_with_content_type_and_path ({HTTP_MIME_TYPES}.text_html, a_path)
+ end
+
+ make (a_file_name: READABLE_STRING_GENERAL)
+ do
+ make_with_path (create {PATH}.make_from_string (a_file_name))
+ end
+
+ make_with_content_type (a_content_type: READABLE_STRING_8; a_file_name: READABLE_STRING_GENERAL)
+ -- Initialize `Current'.
+ do
+ make_with_content_type_and_path (a_content_type, create {PATH}.make_from_string (a_file_name))
+ end
+
+ make_html (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
@@ -118,13 +137,21 @@ feature -- Access
content_type: READABLE_STRING_8
-- Content-Type of the response
+ file_path: path
+ -- File path
+
file_name: READABLE_STRING_8
+ obsolete
+ "Use `file_path.name' for unicode support [2013-may]"
+ do
+ Result := file_path.utf_8_name
+ end
file_exists: BOOLEAN
-- File exists?
file_size: INTEGER
- -- Size of file named `file_name'
+ -- Size of file `file_path'
head, bottom: detachable READABLE_STRING_8
-- Eventual head and bottom part
@@ -184,7 +211,7 @@ feature {WSF_RESPONSE} -- Output
res.put_string (s)
end
if not answer_head_request_method then
- send_file_content_to (file_name, res)
+ send_file_content_to (file_path, res)
end
s := bottom
if s /= Void then
@@ -200,40 +227,37 @@ feature {NONE} -- Implementation: file system helper
local
f: RAW_FILE
do
- create f.make (file_name)
+ create f.make_with_path (file_path)
file_exists := f.exists
end
get_file_size
- -- Get `file_size' from file named `file_name'
+ -- Get `file_size' from file named `file_path'
require
file_exists: file_exists
local
f: RAW_FILE
do
- create f.make (file_name)
+ create f.make_with_path (file_path)
file_size := f.count
end
file_last_modified: detachable DATE_TIME
- -- Get `file_size' from file named `file_name'
+ -- Get `file_size' from file named `file_path'
require
file_exists: file_exists
local
f: RAW_FILE
do
- create f.make (file_name)
+ create f.make_with_path (file_path)
create Result.make_from_epoch (f.change_date)
end
- file_extension (fn: STRING): STRING
+ file_extension (fn: PATH): STRING_32
-- Extension of file `fn'.
- local
- p: INTEGER
do
- p := fn.last_index_of ('.', fn.count)
- if p > 0 then
- Result := fn.substring (p + 1, fn.count)
+ if attached fn.extension as ext then
+ Result := ext
else
create Result.make_empty
end
@@ -242,13 +266,13 @@ feature {NONE} -- Implementation: file system helper
feature -- Content-type related
get_content_type
- -- Content type associated with `file_name'
+ -- Content type associated with `file_path'
local
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
m: detachable READABLE_STRING_8
do
create m_map.make_default
- m := m_map.mime_type (file_extension (file_name).as_lower)
+ m := m_map.mime_type (file_extension (file_path).as_lower)
if m = Void then
m := {HTTP_MIME_TYPES}.application_force_download
end
@@ -257,16 +281,16 @@ feature -- Content-type related
feature {NONE} -- Implementation: output
- send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
+ send_file_content_to (fn: PATH; res: WSF_RESPONSE)
-- Send the content of file `fn'
require
string_not_empty: not fn.is_empty
- is_readable: (create {RAW_FILE}.make (fn)).is_readable
+ is_readable: (create {RAW_FILE}.make_with_path (fn)).is_readable
file_exists: file_exists
local
f: RAW_FILE
do
- create f.make (fn)
+ create f.make_with_path (fn)
check f.is_readable end
f.open_read
diff --git a/library/server/wsf/src/service/wsf_service_launcher_options.e b/library/server/wsf/src/service/wsf_service_launcher_options.e
index bdcd88b5..fd690f88 100644
--- a/library/server/wsf/src/service/wsf_service_launcher_options.e
+++ b/library/server/wsf/src/service/wsf_service_launcher_options.e
@@ -15,7 +15,7 @@ class
WSF_SERVICE_LAUNCHER_OPTIONS
inherit
- ANY
+ TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]
redefine
default_create
end
@@ -23,7 +23,8 @@ inherit
create
default_create,
make,
- make_from_array
+ make_from_array,
+ make_from_iterable
convert
make_from_array ({ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]})
@@ -44,6 +45,19 @@ feature {NONE} -- Initialization
make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
do
make
+ append_array_of_options (a_options)
+ end
+
+ make_from_iterable (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
+ do
+ make
+ append_options (a_options)
+ end
+
+feature -- Merging
+
+ append_array_of_options (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
+ do
across
a_options as opt
loop
@@ -53,6 +67,15 @@ feature {NONE} -- Initialization
end
end
+ append_options (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
+ do
+ across
+ a_options as o
+ loop
+ set_option (o.key, o.item)
+ end
+ end
+
feature -- Access
option (a_name: READABLE_STRING_GENERAL): detachable ANY
@@ -60,6 +83,14 @@ feature -- Access
Result := options.item (a_name)
end
+feature -- Access
+
+ new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL]
+ -- Fresh cursor associated with current structure
+ do
+ Result := options.new_cursor
+ end
+
feature -- Element change
set_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
@@ -75,13 +106,13 @@ feature -- Element change
feature {NONE} -- Implementation
- options: HASH_TABLE [detachable ANY, READABLE_STRING_GENERAL]
+ options: STRING_TABLE [detachable ANY]
-- Custom options which might be support (or not) by the default service
invariant
options_attached: options /= Void
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/src/service/wsf_service_launcher_options_from_ini.e b/library/server/wsf/src/service/wsf_service_launcher_options_from_ini.e
index edb60736..4b2658c5 100644
--- a/library/server/wsf/src/service/wsf_service_launcher_options_from_ini.e
+++ b/library/server/wsf/src/service/wsf_service_launcher_options_from_ini.e
@@ -11,28 +11,40 @@ inherit
WSF_SERVICE_LAUNCHER_OPTIONS
create
- make_from_file
+ make_from_file,
+ make_from_file_and_defaults
feature {NONE} -- Initialization
- make_from_file (a_filename: READABLE_STRING_32)
+ make_from_file (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make
import (a_filename)
end
+ make_from_file_and_defaults (a_filename: READABLE_STRING_GENERAL; dft: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
+ -- Initialize `Current'.
+ do
+ make
+
+ if dft /= Void then
+ append_options (dft)
+ end
+
+ import (a_filename)
+ end
+
feature {NONE} -- Implementation
- import (a_filename: READABLE_STRING_32)
+ import (a_filename: READABLE_STRING_GENERAL)
-- Import ini file content
local
f: PLAIN_TEXT_FILE
l,v: STRING_8
p: INTEGER
do
- --FIXME: handle unicode filename here.
- create f.make (a_filename)
+ create f.make_with_name (a_filename)
if f.exists and f.is_readable then
f.open_read
from
@@ -60,7 +72,7 @@ feature {NONE} -- Implementation
end
note
- copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
+ copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/server/wsf/src/wsf_request.e b/library/server/wsf/src/wsf_request.e
index a59a839d..6b9eb159 100644
--- a/library/server/wsf/src/wsf_request.e
+++ b/library/server/wsf/src/wsf_request.e
@@ -26,6 +26,18 @@ class
inherit
DEBUG_OUTPUT
+ SHARED_EXECUTION_ENVIRONMENT
+ export
+ {NONE} all
+ end
+
+ SHARED_WSF_PERCENT_ENCODER
+ rename
+ percent_encoder as url_encoder
+ export
+ {NONE} all
+ end
+
create {WSF_TO_WGI_SERVICE}
make_from_wgi
@@ -40,26 +52,25 @@ feature {NONE} -- Initialization
do
wgi_request := r
- create string_equality_tester
if attached r.meta_variables as l_vars then
- create tb.make_with_key_tester (l_vars.count, string_equality_tester)
+ create tb.make_equal (l_vars.count)
across
l_vars as c
loop
- tb.force (new_string_value (c.key, c.item), c.key)
+ if attached {READABLE_STRING_8} c.key as s8 then
+ tb.force (new_string_value (s8, c.item), c.key)
+ else
+ tb.force (new_string_value (url_encoded_string (c.key), c.item), c.key)
+ end
end
else
- create tb.make_with_key_tester (0, string_equality_tester)
+ create tb.make_equal (0)
end
meta_variables_table := tb
- meta_variables := tb
create error_handler.make
- create uploaded_files_table.make_with_key_tester (0, string_equality_tester)
+ create uploaded_files_table.make_equal (0)
set_raw_input_data_recorded (False)
- create {IMMUTABLE_STRING_32} empty_string.make_empty
-
- create execution_variables_table.make_with_key_tester (0, string_equality_tester)
- execution_variables_table.compare_objects
+ create execution_variables_table.make_equal (0)
initialize
analyze
@@ -96,12 +107,13 @@ feature {NONE} -- Initialization
request_method := req.request_method
--| PATH_INFO
- path_info := raw_url_encoder.decoded_string (req.path_info)
+ percent_encoded_path_info := req.path_info
+ path_info := url_decoded_string (req.path_info)
--| PATH_TRANSLATED
s8 := req.path_translated
if s8 /= Void then
- path_translated := raw_url_encoder.decoded_string (s8)
+ path_translated := url_decoded_string (s8)
end
--| Here one can set its own environment entries if needed
@@ -111,6 +123,7 @@ feature {NONE} -- Initialization
end
wgi_request: WGI_REQUEST
+ -- Associated WGI request
feature -- Destroy
@@ -125,6 +138,26 @@ feature -- Destroy
loop
delete_uploaded_file (c.item)
end
+
+ content_length_value := 0
+ content_type := Void
+ execution_variables_table.wipe_out
+ internal_cookies_table := Void
+ internal_form_data_parameters_table := Void
+ internal_query_parameters_table := Void
+ internal_server_url := Void
+ internal_url_base := Void
+ form_parameters_table.wipe_out
+ mime_handlers := Void
+ path_info := empty_string_32
+ path_parameters_source := Void
+ path_parameters_table := Void
+ path_translated := Void
+ raw_input_data := Void
+ raw_input_data_recorded := False
+ request_method := empty_string_8
+ set_uploaded_file_path (Void)
+-- wgi_request
end
feature -- Status report
@@ -353,12 +386,12 @@ feature {WSF_REQUEST_EXPORTER} -- Override value
feature {NONE} -- Access: global variable
- items_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ items_table: STRING_TABLE [WSF_VALUE]
-- Table containing all the various variables
-- Warning: this is computed each time, if you change the content of other containers
-- this won't update this Result's content, unless you query it again
do
- create Result.make_with_key_tester (20, string_equality_tester)
+ create Result.make_equal (20)
if attached path_parameters as l_path_parameters then
across
@@ -558,7 +591,7 @@ feature -- Execution variables
feature {NONE} -- Execution variables: implementation
- execution_variables_table: HASH_TABLE_EX [detachable ANY, READABLE_STRING_GENERAL]
+ execution_variables_table: STRING_TABLE [detachable ANY]
feature -- Access: CGI Meta variables
@@ -582,6 +615,9 @@ feature -- Access: CGI Meta variables
meta_variables: ITERABLE [WSF_STRING]
-- CGI meta variables values
+ do
+ Result := meta_variables_table
+ end
meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32
-- Value for meta parameter `a_name'
@@ -617,7 +653,7 @@ feature -- Access: CGI Meta variables
feature {NONE} -- Access: CGI meta parameters
- meta_variables_table: HASH_TABLE_EX [WSF_STRING, READABLE_STRING_GENERAL]
+ meta_variables_table: STRING_TABLE [WSF_STRING]
-- CGI Environment parameters
feature -- Access: CGI meta parameters - 1.1
@@ -739,6 +775,11 @@ feature -- Access: CGI meta parameters - 1.1
Result := wgi_request.gateway_interface
end
+ percent_encoded_path_info: READABLE_STRING_8
+ -- Non decoded PATH_INFO value from CGI.
+ -- See `path_info' for the related percent decoded value.
+ --| This value should be used by component dealing only with ASCII path
+
path_info: READABLE_STRING_32
-- The PATH_INFO metavariable specifies a path to be interpreted
-- by the CGI script. It identifies the resource or sub-resource
@@ -767,6 +808,8 @@ feature -- Access: CGI meta parameters - 1.1
-- The PATH_INFO value is case-sensitive, and the server MUST
-- preserve the case of the PATH_INFO element of the URI when
-- making it available to scripts.
+ --
+ -- See `percent_encoded_path_info' to get the original non decoded path info.
path_translated: detachable READABLE_STRING_32
-- PATH_TRANSLATED is derived by taking any path-info component
@@ -1150,7 +1193,7 @@ feature -- Cookies
feature {NONE} -- Cookies
- cookies_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ cookies_table: STRING_TABLE [WSF_VALUE]
-- Expanded cookies variable
local
i,j,p,n: INTEGER
@@ -1161,8 +1204,7 @@ feature {NONE} -- Cookies
if l_cookies = Void then
if attached {WSF_STRING} meta_variable ({WSF_META_NAMES}.http_cookie) as val then
s := val.value
- create l_cookies.make_with_key_tester (5, string_equality_tester)
- l_cookies.compare_objects
+ create l_cookies.make_equal (5)
from
n := s.count
p := 1
@@ -1190,8 +1232,7 @@ feature {NONE} -- Cookies
end
end
else
- create l_cookies.make_with_key_tester (0, string_equality_tester)
- l_cookies.compare_objects
+ create l_cookies.make_equal (0)
end
internal_cookies_table := l_cookies
end
@@ -1217,7 +1258,7 @@ feature -- Path parameters
feature {NONE} -- Query parameters: implementation
- path_parameters_table: detachable HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ path_parameters_table: detachable STRING_TABLE [WSF_VALUE]
-- Parameters computed from `path_parameters_source'
--| most often coming from the associated route from WSF_ROUTER
@@ -1240,8 +1281,7 @@ feature {WSF_REQUEST_PATH_PARAMETERS_SOURCE} -- Path parameters: Element change
if l_count = 0 then
l_table := Void
else
- create l_table.make_with_key_tester (l_count, string_equality_tester)
- l_table.compare_objects
+ create l_table.make_equal (l_count)
if attached src.path_parameters as tb then
across
tb as c
@@ -1278,7 +1318,7 @@ feature -- Query parameters
feature {NONE} -- Query parameters: implementation
- query_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ query_parameters_table: STRING_TABLE [WSF_VALUE]
-- Parameters extracted from QUERY_STRING
local
vars: like internal_query_parameters_table
@@ -1303,13 +1343,12 @@ feature {NONE} -- Query parameters: implementation
end
end
vars := urlencoded_parameters (s)
- vars.compare_objects
internal_query_parameters_table := vars
end
Result := vars
end
- urlencoded_parameters (a_content: detachable READABLE_STRING_8): HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ urlencoded_parameters (a_content: detachable READABLE_STRING_8): STRING_TABLE [WSF_VALUE]
-- Import `a_content'
local
n, p, i, j: INTEGER
@@ -1317,13 +1356,13 @@ feature {NONE} -- Query parameters: implementation
l_name, l_value: READABLE_STRING_8
do
if a_content = Void then
- create Result.make_with_key_tester (0, string_equality_tester)
+ create Result.make_equal (0)
else
n := a_content.count
if n = 0 then
- create Result.make_with_key_tester (0, string_equality_tester)
+ create Result.make_equal (0)
else
- create Result.make_with_key_tester (3, string_equality_tester) --| 3 = arbitrary value
+ create Result.make_equal (3) --| 3 = arbitrary value
from
p := 1
until
@@ -1348,6 +1387,8 @@ feature {NONE} -- Query parameters: implementation
end
end
end
+ ensure
+ result_with_object_comparison: Result.object_comparison
end
feature -- Form fields and related
@@ -1452,7 +1493,7 @@ feature {NONE} -- Implementation: MIME handler
feature {NONE} -- Form fields and related
- uploaded_files_table: HASH_TABLE_EX [WSF_UPLOADED_FILE, READABLE_STRING_GENERAL]
+ uploaded_files_table: STRING_TABLE [WSF_UPLOADED_FILE]
get_form_parameters
-- Variables sent by POST, ... request
@@ -1464,14 +1505,12 @@ feature {NONE} -- Form fields and related
vars := internal_form_data_parameters_table
if vars = Void then
if not is_chunked_input and content_length_value = 0 then
- create vars.make_with_key_tester (0, string_equality_tester)
- vars.compare_objects
+ create vars.make_equal (0)
else
if raw_input_data_recorded then
create l_raw_data_cell.put (Void)
end
- create vars.make_with_key_tester (5, string_equality_tester)
- vars.compare_objects
+ create vars.make_equal (5)
l_type := content_type
if l_type /= Void and then attached mime_handler (l_type) as hdl then
@@ -1488,7 +1527,7 @@ feature {NONE} -- Form fields and related
internal_form_data_parameters_table /= Void
end
- form_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
+ form_parameters_table: STRING_TABLE [WSF_VALUE]
-- Variables sent by POST request
local
vars: like internal_form_data_parameters_table
@@ -1497,14 +1536,14 @@ feature {NONE} -- Form fields and related
vars := internal_form_data_parameters_table
if vars = Void then
check form_parameters_already_retrieved: False end
- create vars.make_with_key_tester (0, string_equality_tester)
+ create vars.make_equal (0)
end
Result := vars
end
feature {NONE} -- Implementation: smart parameter identification
- add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
+ add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: STRING_TABLE [WSF_VALUE])
-- Add urlencoded parameter `a_name'=`a_value' to `a_table'
-- following smart computation such as handling the "..[..]" as table
local
@@ -1548,7 +1587,7 @@ feature {NONE} -- Implementation: smart parameter identification
if p > 0 then
q := r.index_of ({CHARACTER_8} ']', p + 1)
if q > p then
- k32 := url_encoder.decoded_string (k)
+ k32 := url_decoded_string (k)
if attached {WSF_TABLE} ptb.value (k32) as l_tb_value then
tb := l_tb_value
else
@@ -1610,7 +1649,7 @@ feature -- Uploaded File Handling
until
l_files.after or Result
loop
- if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string_general (a_filename) then
+ if attached l_files.item_for_iteration.tmp_path as l_tmp_path and then a_filename.same_string (l_tmp_path.name) then
Result := True
end
l_files.forth
@@ -1686,7 +1725,7 @@ feature -- URL Utility
elseif spos > 0 then
i := spos
end
- spos := l_rq_uri.substring_index (path_info, i)
+ spos := l_rq_uri.substring_index (percent_encoded_path_info, i)
if spos > 0 then
l_base_url := l_rq_uri.substring (1, spos - 1)
else
@@ -1736,18 +1775,18 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
f: RAW_FILE
do
if uploaded_files_table.has_item (uf) then
- if attached uf.tmp_name as fn then
- create f.make (fn)
+ if attached uf.tmp_path as fn then
+ create f.make_with_path (fn)
if f.exists and then f.is_writable then
f.delete
else
- error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete file %""+ fn +"%"")
+ error_handler.add_custom_error (0, "Can not delete uploaded file", {STRING_32} "Can not delete file %""+ fn.name + {STRING_32} "%"")
end
else
- error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete uploaded file %""+ uf.name +"%" Tmp File not found")
+ error_handler.add_custom_error (0, "Can not delete uploaded file", {STRING_32} "Can not delete uploaded file %""+ uf.name + {STRING_32} "%" Tmp File not found")
end
else
- error_handler.add_custom_error (0, "Not an uploaded file", "This file %""+ uf.name +"%" is not an uploaded file.")
+ error_handler.add_custom_error (0, "Not an uploaded file", {STRING_32} "This file %""+ uf.name + {STRING_32} "%" is not an uploaded file.")
end
end
@@ -1757,8 +1796,8 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
bn: STRING
l_safe_name: STRING
f: RAW_FILE
- dn: STRING
- fn: FILE_NAME
+ dn: PATH
+ fn: PATH
d: DIRECTORY
n: INTEGER
rescued: BOOLEAN
@@ -1768,30 +1807,28 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
dn := p
else
-- FIXME: should it be configured somewhere?
- dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory
+ dn := execution_environment.current_working_path
end
- create d.make (dn)
+ create d.make_with_path (dn)
if d.exists and then d.is_writable then
l_safe_name := a_up_file.safe_filename
from
- create fn.make_from_string (dn)
- bn := "EWF_tmp-" + l_safe_name
- fn.set_file_name (bn)
- create f.make (fn.string)
+ bn := "tmp-" + l_safe_name
+ fn := dn.extended (bn)
+ create f.make_with_path (fn)
n := 0
until
not f.exists
or else n > 1_000
loop
n := n + 1
- fn.make_from_string (dn)
- bn := "EWF_tmp-" + n.out + "-" + l_safe_name
- fn.set_file_name (bn)
- f.make (fn.string)
+ bn := "tmp-" + n.out + "-" + l_safe_name
+ fn := dn.extended (bn)
+ f.make_with_path (fn)
end
if not f.exists or else f.is_writable then
- a_up_file.set_tmp_name (f.name)
+ a_up_file.set_tmp_path (f.path)
a_up_file.set_tmp_basename (bn)
f.open_write
f.put_string (a_content)
@@ -1800,7 +1837,7 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
a_up_file.set_error (-1)
end
else
- error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"")
+ error_handler.add_custom_error (0, "Directory not writable", {STRING_32} "Can not create file in directory %""+ dn.name + {STRING_32} "%"")
end
uploaded_files_table.force (a_up_file, a_up_file.name)
else
@@ -1813,13 +1850,13 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
feature {WSF_REQUEST_EXPORTER} -- Settings
- uploaded_file_path: detachable READABLE_STRING_8
+ uploaded_file_path: detachable PATH
-- Optional folder path used to store uploaded files
set_uploaded_file_path (p: like uploaded_file_path)
-- Set `uploaded_file_path' to `p'.
require
- path_exists: p /= Void implies (create {DIRECTORY}.make (p)).exists
+ path_exists: p /= Void implies (create {DIRECTORY}.make_with_path (p)).exists
do
uploaded_file_path := p
end
@@ -1874,8 +1911,6 @@ feature {NONE} -- Implementation
feature {NONE} -- Implementation: utilities
- string_equality_tester: STRING_EQUALITY_TESTER
-
single_slash_starting_string (s: READABLE_STRING_32): STRING_32
-- Return the string `s' (or twin) with one and only one starting slash
local
@@ -1927,17 +1962,27 @@ feature {NONE} -- Implementation: utilities
create Result.make (a_name, a_value)
end
- empty_string: READABLE_STRING_32
+ empty_string_32: IMMUTABLE_STRING_32
-- Reusable empty string
-
- raw_url_encoder: URL_ENCODER
once
- create {URL_ENCODER} Result
+ create Result.make_empty
end
- url_encoder: URL_ENCODER
+ empty_string_8: IMMUTABLE_STRING_8
once
- create {UTF8_URL_ENCODER} Result
+ create Result.make_empty
+ end
+
+ url_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
+ do
+ create Result.make (s.count)
+ url_encoder.append_percent_encoded_string_to (s, Result)
+ end
+
+ url_decoded_string (s: READABLE_STRING_GENERAL): STRING_32
+ do
+ create Result.make (s.count)
+ url_encoder.append_percent_decoded_string_to (s, Result)
end
date_time_utilities: HTTP_DATE_TIME_UTILITIES
@@ -1947,7 +1992,8 @@ feature {NONE} -- Implementation: utilities
end
invariant
- empty_string_unchanged: empty_string.is_empty
+ empty_string_32_unchanged: empty_string_32.is_empty
+ empty_string_8_unchanged: empty_string_8.is_empty
wgi_request.content_type /= Void implies content_type /= Void
note
diff --git a/library/text/encoder/encoder-safe.ecf b/library/text/encoder/encoder-safe.ecf
index 9bd23d7e..b7307359 100644
--- a/library/text/encoder/encoder-safe.ecf
+++ b/library/text/encoder/encoder-safe.ecf
@@ -11,22 +11,10 @@
-
/tests$
- /spec$
-
-
-
-
-
-
-
-
-
-
diff --git a/library/text/encoder/encoder.ecf b/library/text/encoder/encoder.ecf
index 71732816..781d7fb6 100644
--- a/library/text/encoder/encoder.ecf
+++ b/library/text/encoder/encoder.ecf
@@ -11,22 +11,10 @@
-
/tests$
- /spec$
-
-
-
-
-
-
-
-
-
-
diff --git a/library/text/encoder/src/spec/70/utf8_encoder_helper.e b/library/text/encoder/src/shared_utf8_url_encoder.e
similarity index 50%
rename from library/text/encoder/src/spec/70/utf8_encoder_helper.e
rename to library/text/encoder/src/shared_utf8_url_encoder.e
index 8e82c656..be64e925 100644
--- a/library/text/encoder/src/spec/70/utf8_encoder_helper.e
+++ b/library/text/encoder/src/shared_utf8_url_encoder.e
@@ -1,26 +1,21 @@
note
- description : "Objects that ..."
- author : "$Author$"
- date : "$Date$"
- revision : "$Revision$"
+ description: "Objects to access the shared once UTF8_URL_ENCODER ..."
+ date: "$Date$"
+ revision: "$Revision$"
-deferred class
- UTF8_ENCODER_HELPER
+class
+ SHARED_UTF8_URL_ENCODER
-inherit
- ANY
+feature -- Encoder
- UNICODE_CONVERSION
- export
- {NONE} all
- {ANY} is_valid_utf8
- undefine
- is_little_endian
+ url_encoder: UTF8_URL_ENCODER
+ -- Shared UTF8 URL encoder.
+ once
+ create Result
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
@@ -29,4 +24,5 @@ note
Website http://www.eiffel.com
Customer support http://support.eiffel.com
]"
+
end
diff --git a/library/text/encoder/src/spec/before_70/utf8_encoder_helper.e b/library/text/encoder/src/spec/before_70/utf8_encoder_helper.e
deleted file mode 100644
index e8e996e3..00000000
--- a/library/text/encoder/src/spec/before_70/utf8_encoder_helper.e
+++ /dev/null
@@ -1,73 +0,0 @@
-note
- description : "Objects that ..."
- author : "$Author$"
- date : "$Date$"
- revision : "$Revision$"
-
-deferred class
- UTF8_ENCODER_HELPER
-
-inherit
- ANY
-
- UNICODE_CONVERSION
- export
- {NONE} all
- undefine
- is_little_endian
- end
-
-feature -- Status report
-
- is_valid_utf8 (a_string: STRING): BOOLEAN
- -- Is `a_string' valid UTF-8 string?
- require
- a_string_not_void: a_string /= Void
- local
- l_nat8: NATURAL_8
- l_code: NATURAL_32
- i, nb: INTEGER
- do
- from
- i := 1
- nb := a_string.count
- Result := True
- until
- i > nb or not Result
- loop
- l_nat8 := a_string.code (i).to_natural_8
- if l_nat8 <= 127 then
- -- Form 0xxxxxxx.
- elseif (l_nat8 & 0xE0) = 0xC0 then
- -- Form 110xxxxx 10xxxxxx.
- l_code := (l_nat8 & 0x1F).to_natural_32 |<< 6
- i := i + 1
- elseif (l_nat8 & 0xF0) = 0xE0 then
- -- Form 1110xxxx 10xxxxxx 10xxxxxx.
- i := i + 2
- elseif (l_nat8 & 0xF8) = 0xF0 then
- -- Form 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
- i := i + 3
- elseif (l_nat8 & 0xFC) = 0xF8 then
- -- Starts with 111110xx
- Result := False
- else
- -- Starts with 1111110x
- Result := False
- end
- i := i + 1
- end
- end
-
-
-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/text/encoder/src/utf8_encoder.e b/library/text/encoder/src/utf8_encoder.e
index 778ee000..50ad4acd 100644
--- a/library/text/encoder/src/utf8_encoder.e
+++ b/library/text/encoder/src/utf8_encoder.e
@@ -15,8 +15,6 @@ class
inherit
ENCODER [READABLE_STRING_32, READABLE_STRING_8]
- UTF8_ENCODER_HELPER
-
PLATFORM
export
{NONE} all
@@ -37,9 +35,13 @@ feature -- Encoder
encoded_string (s: READABLE_STRING_32): STRING_8
-- UTF8-encoded value of `s'.
+ do
+ Result := general_encoded_string (s)
+ end
+
+ general_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
do
Result := utf32_to_utf8 (s)
- has_error := not last_conversion_successful
end
feature -- Decoder
@@ -48,11 +50,34 @@ feature -- Decoder
-- The UTF8-encoded equivalent of the given string
do
Result := utf8_to_utf32 (v)
- has_error := not last_conversion_successful
+ has_error := not is_valid_utf8 (v)
+ end
+
+feature {NONE} -- UTF implementation
+
+ utf32_to_utf8 (s: READABLE_STRING_GENERAL): STRING_8
+ local
+ utf: UTF_CONVERTER
+ do
+ Result := utf.utf_32_string_to_utf_8_string_8 (s)
+ end
+
+ utf8_to_utf32 (s: READABLE_STRING_8): STRING_32
+ local
+ utf: UTF_CONVERTER
+ do
+ Result := utf.utf_8_string_8_to_string_32 (s)
+ end
+
+ is_valid_utf8 (s: READABLE_STRING_8): BOOLEAN
+ local
+ utf: UTF_CONVERTER
+ do
+ Result := utf.is_valid_utf_8_string_8 (s)
end
note
- copyright: "2011-2012, Eiffel Software and others"
+ copyright: "2011-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/library/text/encoder/src/utf8_url_encoder.e b/library/text/encoder/src/utf8_url_encoder.e
index 1931e95a..1edfef50 100644
--- a/library/text/encoder/src/utf8_url_encoder.e
+++ b/library/text/encoder/src/utf8_url_encoder.e
@@ -15,23 +15,24 @@ class
inherit
URL_ENCODER
redefine
- default_create,
name,
general_encoded_string,
encoded_string, partial_encoded_string,
decoded_string
+ select
+ encoded_string,
+ decoded_string,
+ has_error
end
- UTF8_ENCODER_HELPER
+ UTF8_ENCODER
+ rename
+ general_encoded_string as utf8_general_encoded_string,
+ encoded_string as utf8_encoded_string,
+ decoded_string as utf8_decoded_string,
+ has_error as utf8_has_error
redefine
- default_create
- end
-
-feature {NONE} -- Initialization
-
- default_create
- do
- Precursor {UTF8_ENCODER_HELPER}
+ name
end
feature -- Access
@@ -46,27 +47,22 @@ feature -- Encoder
encoded_string (s: READABLE_STRING_32): STRING_8
-- URL-encoded value of `s'.
do
- Result := utf32_to_utf8 (s)
- Result := Precursor (Result)
+ Result := general_encoded_string (s)
end
general_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
do
- if attached {READABLE_STRING_32} s as s32 then
- Result := utf32_to_utf8 (s32)
- else
- Result := s.as_string_8
- end
- Result := Precursor (Result)
+ Result := utf8_general_encoded_string (s)
+ Result := Precursor {URL_ENCODER} (Result)
+ has_error := has_error or utf8_has_error
end
partial_encoded_string (s: READABLE_STRING_GENERAL; a_ignore: ARRAY [CHARACTER]): STRING_8
-- URL-encoded value of `s'.
do
- Result := Precursor (s, a_ignore)
- if not has_error then
- Result := utf32_to_utf8 (Result)
- end
+ Result := utf8_general_encoded_string (s)
+ Result := Precursor {URL_ENCODER} (Result, a_ignore)
+ has_error := has_error or utf8_has_error
end
feature -- Decoder
@@ -74,17 +70,15 @@ feature -- Decoder
decoded_string (v: READABLE_STRING_8): STRING_32
-- The URL-encoded equivalent of the given string
do
- Result := Precursor (v)
+ Result := Precursor {URL_ENCODER} (v)
if not has_error then
- if is_valid_utf8 (Result) then
- Result := utf8_to_utf32 (Result)
- has_error := not last_conversion_successful
- end
+ Result := utf8_decoded_string (Result)
+ has_error := utf8_has_error
end
end
note
- copyright: "2011-2012, Eiffel Software and others"
+ copyright: "2011-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software
diff --git a/tools/bin/ecf_updater.exe b/tools/bin/ecf_updater.exe
new file mode 100644
index 00000000..e4e515cf
Binary files /dev/null and b/tools/bin/ecf_updater.exe differ