Better support for unicode path and values.
Added WSF_REQUEST.percent_encoded_path_info: READABLE_STRING_8
to keep url encoded path info, as it is useful for specific component
The router is now using WSF_REQUEST.percent_encoded_path_info
since URI_TEMPLATE are handling URI (and not IRI)
this fixes an issue with unicode path parameters.
This should not break existing code, and this fixes various unicode related issues related
to PATH parameter and path info
but also any component using file names.
(required EiffelStudio >= 7.2)
This commit is contained in:
@@ -10,6 +10,10 @@ class
|
|||||||
|
|
||||||
inherit
|
inherit
|
||||||
WSF_URI_TEMPLATE_RESPONSE_HANDLER
|
WSF_URI_TEMPLATE_RESPONSE_HANDLER
|
||||||
|
SHARED_WSF_PERCENT_ENCODER
|
||||||
|
rename
|
||||||
|
percent_encoder as url_encoder
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
@@ -75,7 +79,8 @@ feature -- Access
|
|||||||
|
|
||||||
url_encoded_string (s: READABLE_STRING_32): STRING_8
|
url_encoded_string (s: READABLE_STRING_32): STRING_8
|
||||||
do
|
do
|
||||||
Result := (create {UTF8_URL_ENCODER}).encoded_string (s)
|
create Result.make (s.count)
|
||||||
|
url_encoder.append_percent_encoded_string_to (s, Result)
|
||||||
end
|
end
|
||||||
|
|
||||||
html_decoded_string (v: READABLE_STRING_32): READABLE_STRING_32
|
html_decoded_string (v: READABLE_STRING_32): READABLE_STRING_32
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ feature {NONE} -- Initialization
|
|||||||
-- Create with no mapping
|
-- Create with no mapping
|
||||||
-- but one can use `map' to add new mapping
|
-- but one can use `map' to add new mapping
|
||||||
do
|
do
|
||||||
create mapping.make (n)
|
create mapping.make_caseless (n)
|
||||||
mapping.compare_objects
|
|
||||||
end
|
end
|
||||||
|
|
||||||
make_default
|
make_default
|
||||||
@@ -43,9 +42,8 @@ feature {NONE} -- Initialization
|
|||||||
local
|
local
|
||||||
m: like mapping
|
m: like mapping
|
||||||
do
|
do
|
||||||
create m.make (40)
|
create m.make_caseless (40)
|
||||||
mapping := m
|
mapping := m
|
||||||
m.compare_objects
|
|
||||||
m.force (text_css, "css")
|
m.force (text_css, "css")
|
||||||
m.force (text_html, "html")
|
m.force (text_html, "html")
|
||||||
m.force (text_xml, "xml")
|
m.force (text_xml, "xml")
|
||||||
@@ -74,13 +72,13 @@ feature {NONE} -- Initialization
|
|||||||
m.force (text_plain, "txt")
|
m.force (text_plain, "txt")
|
||||||
end
|
end
|
||||||
|
|
||||||
make_from_file (fn: READABLE_STRING_8)
|
make_from_file (fn: READABLE_STRING_GENERAL)
|
||||||
-- Create with mime.types file
|
-- Create with mime.types file
|
||||||
-- One can use `map' to add new mapping
|
-- One can use `map' to add new mapping
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (fn)
|
create f.make_with_name (fn)
|
||||||
if f.exists and then f.is_readable then
|
if f.exists and then f.is_readable then
|
||||||
make_empty (50)
|
make_empty (50)
|
||||||
f.open_read
|
f.open_read
|
||||||
@@ -128,7 +126,7 @@ feature {NONE} -- Initialization
|
|||||||
|
|
||||||
feature -- Access
|
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'
|
-- Mime type for extension `ext'
|
||||||
do
|
do
|
||||||
Result := mapping.item (ext.as_lower)
|
Result := mapping.item (ext.as_lower)
|
||||||
@@ -136,7 +134,7 @@ feature -- Access
|
|||||||
|
|
||||||
feature -- Element change
|
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'
|
-- Add mapping extension `e' to mime type `t'
|
||||||
do
|
do
|
||||||
mapping.force (t, e.as_lower)
|
mapping.force (t, e.as_lower)
|
||||||
@@ -220,13 +218,13 @@ feature {NONE} -- Implementation
|
|||||||
|
|
||||||
feature {NONE} -- Extension MIME mapping
|
feature {NONE} -- Extension MIME mapping
|
||||||
|
|
||||||
mapping: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
|
mapping: STRING_TABLE [READABLE_STRING_8]
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
mapping_keys_are_lowercase: across mapping as c all c.key.same_string (c.key.as_lower) end
|
mapping_keys_are_lowercase: across mapping as c all c.key.same_string (c.key.as_lower) end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ feature {WSF_RESPONSE} -- Output
|
|||||||
|
|
||||||
debug
|
debug
|
||||||
l_description.append ("<h2>Meta Information</h2><ul>")
|
l_description.append ("<h2>Meta Information</h2><ul>")
|
||||||
l_description.append ("<li>PATH_INFO=" + request.path_info + "</li>")
|
l_description.append ("<li>PATH_INFO=" + request.percent_encoded_path_info + "</li>")
|
||||||
l_description.append ("<li>QUERY_STRING=" + request.query_string + "</li>")
|
l_description.append ("<li>QUERY_STRING=" + request.query_string + "</li>")
|
||||||
l_description.append ("<li>REQUEST_URI=" + request.request_uri + "</li>")
|
l_description.append ("<li>REQUEST_URI=" + request.request_uri + "</li>")
|
||||||
l_description.append ("<li>SCRIPT_NAME=" + request.script_name + "</li>")
|
l_description.append ("<li>SCRIPT_NAME=" + request.script_name + "</li>")
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ feature -- Execution
|
|||||||
a_start_path_attached: a_start_path /= Void
|
a_start_path_attached: a_start_path /= Void
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= 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
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ feature {WSF_ROUTER} -- Mapping
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ feature {NONE} -- Execution
|
|||||||
a_start_path_attached: a_start_path /= Void
|
a_start_path_attached: a_start_path /= Void
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
res_attached: res /= 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
|
deferred
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ feature -- Status
|
|||||||
-- <Precursor>
|
-- <Precursor>
|
||||||
local
|
local
|
||||||
tpl: URI_TEMPLATE
|
tpl: URI_TEMPLATE
|
||||||
p: READABLE_STRING_32
|
p: READABLE_STRING_8
|
||||||
do
|
do
|
||||||
p := path_from_request (req)
|
p := path_from_request (req)
|
||||||
tpl := based_uri_template (template, a_router)
|
tpl := based_uri_template (template, a_router)
|
||||||
@@ -72,7 +72,7 @@ feature -- Status
|
|||||||
-- <Precursor>
|
-- <Precursor>
|
||||||
local
|
local
|
||||||
tpl: URI_TEMPLATE
|
tpl: URI_TEMPLATE
|
||||||
p: READABLE_STRING_32
|
p: READABLE_STRING_8
|
||||||
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
|
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
|
||||||
do
|
do
|
||||||
p := path_from_request (req)
|
p := path_from_request (req)
|
||||||
|
|||||||
@@ -15,31 +15,53 @@ inherit
|
|||||||
|
|
||||||
WSF_SELF_DOCUMENTED_HANDLER
|
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
|
create
|
||||||
|
make_with_path,
|
||||||
|
make_hidden_with_path,
|
||||||
make,
|
make,
|
||||||
make_hidden
|
make_hidden
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (d: like document_root)
|
make_with_path (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
|
|
||||||
do
|
do
|
||||||
if d.is_empty then
|
if d.is_empty then
|
||||||
create e
|
document_root := execution_environment.current_working_path
|
||||||
document_root := e.current_working_directory
|
|
||||||
else
|
else
|
||||||
document_root := d
|
document_root := d
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
not document_root.is_empty and then not document_root.ends_with (operating_environment.directory_separator.out)
|
not document_root.is_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
make_hidden (d: like document_root)
|
make_hidden_with_path (d: like document_root)
|
||||||
require
|
do
|
||||||
valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
|
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
|
do
|
||||||
make (d)
|
make (d)
|
||||||
is_hidden := True
|
is_hidden := True
|
||||||
@@ -60,9 +82,10 @@ feature -- Documentation
|
|||||||
Result.add_description ("File service")
|
Result.add_description ("File service")
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
|
document_root: PATH
|
||||||
|
|
||||||
document_root: STRING
|
|
||||||
max_age: INTEGER
|
max_age: INTEGER
|
||||||
|
|
||||||
index_disabled: BOOLEAN
|
index_disabled: BOOLEAN
|
||||||
@@ -118,10 +141,10 @@ feature -- Execution
|
|||||||
|
|
||||||
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
p: STRING
|
p: STRING_32
|
||||||
do
|
do
|
||||||
p := req.path_info
|
create p.make_from_string (req.path_info)
|
||||||
if p.starts_with (a_start_path) then
|
if p.starts_with_general (a_start_path) then
|
||||||
p.remove_head (a_start_path.count)
|
p.remove_head (a_start_path.count)
|
||||||
else
|
else
|
||||||
check starts_with_base: False end
|
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)
|
execute_starts_with (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
do
|
do
|
||||||
execute (a_start_path,req, res)
|
execute (a_start_path, req, res)
|
||||||
end
|
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
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
fn: READABLE_STRING_8
|
fn: like resource_filename
|
||||||
do
|
do
|
||||||
fn := resource_filename (uri)
|
fn := resource_filename (uri)
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
if f.exists then
|
if f.exists then
|
||||||
if f.is_readable then
|
if f.is_readable then
|
||||||
if f.is_directory then
|
if f.is_directory then
|
||||||
@@ -160,14 +183,15 @@ feature -- Execution
|
|||||||
end
|
end
|
||||||
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
|
local
|
||||||
h: HTTP_HEADER
|
h: HTTP_HEADER
|
||||||
uri, s: STRING_8
|
uri, s: STRING_8
|
||||||
d: DIRECTORY
|
d: DIRECTORY
|
||||||
l_files: LIST [STRING_8]
|
l_files: LIST [PATH]
|
||||||
do
|
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
|
if attached directory_index_file (d) as f then
|
||||||
process_file (f, req, res)
|
process_file (f, req, res)
|
||||||
else
|
else
|
||||||
@@ -187,12 +211,16 @@ feature -- Execution
|
|||||||
s.replace_substring_all ("$URI", uri)
|
s.replace_substring_all ("$URI", uri)
|
||||||
|
|
||||||
from
|
from
|
||||||
l_files := d.linear_representation
|
l_files := d.entries
|
||||||
l_files.start
|
l_files.start
|
||||||
until
|
until
|
||||||
l_files.after
|
l_files.after
|
||||||
loop
|
loop
|
||||||
s.append ("<li><a href=%"" + uri + l_files.item_for_iteration + "%">" + l_files.item_for_iteration + "</a></li>%N")
|
s.append ("<li><a href=%"" + uri)
|
||||||
|
url_encoder.append_percent_encoded_string_to (l_files.item.name, s)
|
||||||
|
s.append ("%">")
|
||||||
|
s.append (html_encoder.encoded_string (l_files.item.name))
|
||||||
|
s.append ("</a></li>%N")
|
||||||
l_files.forth
|
l_files.forth
|
||||||
end
|
end
|
||||||
s.append ("[
|
s.append ("[
|
||||||
@@ -217,12 +245,12 @@ feature -- Execution
|
|||||||
|
|
||||||
process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
|
process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
|
||||||
local
|
local
|
||||||
ext: READABLE_STRING_8
|
ext: READABLE_STRING_32
|
||||||
ct: detachable READABLE_STRING_8
|
ct: detachable READABLE_STRING_8
|
||||||
fres: WSF_FILE_RESPONSE
|
fres: WSF_FILE_RESPONSE
|
||||||
dt: DATE_TIME
|
dt: DATE_TIME
|
||||||
do
|
do
|
||||||
ext := extension (f.name)
|
ext := extension (f.path.name)
|
||||||
ct := extension_mime_mapping.mime_type (ext)
|
ct := extension_mime_mapping.mime_type (ext)
|
||||||
if ct = Void then
|
if ct = Void then
|
||||||
ct := {HTTP_MIME_TYPES}.application_force_download
|
ct := {HTTP_MIME_TYPES}.application_force_download
|
||||||
@@ -235,7 +263,7 @@ feature -- Execution
|
|||||||
then
|
then
|
||||||
process_not_modified (f_date, req, res)
|
process_not_modified (f_date, req, res)
|
||||||
else
|
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)
|
fres.set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
|
|
||||||
-- cache control
|
-- cache control
|
||||||
@@ -341,7 +369,7 @@ feature {NONE} -- Implementation
|
|||||||
directory_index_file (d: DIRECTORY): detachable FILE
|
directory_index_file (d: DIRECTORY): detachable FILE
|
||||||
local
|
local
|
||||||
f: detachable RAW_FILE
|
f: detachable RAW_FILE
|
||||||
fn: FILE_NAME
|
fn: PATH
|
||||||
do
|
do
|
||||||
if attached directory_index as default_index then
|
if attached directory_index as default_index then
|
||||||
across
|
across
|
||||||
@@ -350,12 +378,11 @@ feature {NONE} -- Implementation
|
|||||||
Result /= Void
|
Result /= Void
|
||||||
loop
|
loop
|
||||||
if d.has_entry (c.item) then
|
if d.has_entry (c.item) then
|
||||||
create fn.make_from_string (d.name)
|
fn := d.path.extended (c.item)
|
||||||
fn.set_file_name (c.item)
|
|
||||||
if f = Void then
|
if f = Void then
|
||||||
create f.make (fn.string)
|
create f.make_with_path (fn)
|
||||||
else
|
else
|
||||||
f.make (fn.string)
|
f.make_with_path (fn)
|
||||||
end
|
end
|
||||||
if f.exists and then f.is_readable then
|
if f.exists and then f.is_readable then
|
||||||
Result := f
|
Result := f
|
||||||
@@ -365,28 +392,34 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resource_filename (uri: READABLE_STRING_8): READABLE_STRING_8
|
resource_filename (uri: READABLE_STRING_32): PATH
|
||||||
do
|
|
||||||
Result := real_filename (document_root + operating_environment.directory_separator.out + real_filename (uri))
|
|
||||||
end
|
|
||||||
|
|
||||||
dirname (uri: READABLE_STRING_8): READABLE_STRING_8
|
|
||||||
local
|
local
|
||||||
p: INTEGER
|
s: like uri_path_to_filename
|
||||||
do
|
do
|
||||||
p := uri.last_index_of ('/', uri.count)
|
Result := document_root
|
||||||
if p > 0 then
|
s := uri_path_to_filename (uri)
|
||||||
Result := uri.substring (1, p - 1)
|
if not s.is_empty then
|
||||||
else
|
Result := Result.extended (s)
|
||||||
create {STRING_8} Result.make_empty
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
filename (uri: READABLE_STRING_8): READABLE_STRING_8
|
dirname (uri: READABLE_STRING_32): READABLE_STRING_32
|
||||||
local
|
local
|
||||||
p: INTEGER
|
p: INTEGER
|
||||||
do
|
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
|
if p > 0 then
|
||||||
Result := uri.substring (p + 1, uri.count)
|
Result := uri.substring (p + 1, uri.count)
|
||||||
else
|
else
|
||||||
@@ -394,58 +427,52 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
extension (uri: READABLE_STRING_8): READABLE_STRING_8
|
extension (uri: READABLE_STRING_32): READABLE_STRING_32
|
||||||
local
|
local
|
||||||
p: INTEGER
|
p: INTEGER
|
||||||
do
|
do
|
||||||
p := uri.last_index_of ('.', uri.count)
|
p := uri.last_index_of ({CHARACTER_32} '.', uri.count)
|
||||||
if p > 0 then
|
if p > 0 then
|
||||||
Result := uri.substring (p + 1, uri.count)
|
Result := uri.substring (p + 1, uri.count)
|
||||||
else
|
else
|
||||||
create {STRING_8} Result.make_empty
|
create {STRING_32} Result.make_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
real_filename (fn: STRING): STRING
|
uri_path_to_filename (fn: READABLE_STRING_32): STRING_32
|
||||||
-- Real filename from url-path `fn'
|
-- Real filename from url-path `fn'
|
||||||
--| Find a better design for this piece of code
|
--| Find a better design for this piece of code
|
||||||
--| Eventually in a spec/$ISE_PLATFORM/ specific cluster
|
--| Eventually in a spec/$ISE_PLATFORM/ specific cluster
|
||||||
|
local
|
||||||
|
n: INTEGER
|
||||||
do
|
do
|
||||||
if fn.is_empty then
|
n := fn.count
|
||||||
Result := fn
|
create Result.make_from_string (fn)
|
||||||
else
|
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
|
if {PLATFORM}.is_windows then
|
||||||
create Result.make_from_string (fn)
|
Result.replace_substring_all ({STRING_32} "/", {STRING_32} "\")
|
||||||
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
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
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
|
extension_mime_mapping: HTTP_FILE_EXTENSION_MIME_MAPPING
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
once
|
once
|
||||||
create f.make ("mime.types")
|
create f.make_with_name ("mime.types")
|
||||||
if f.exists and then f.is_readable then
|
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
|
else
|
||||||
create Result.make_default
|
create Result.make_default
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ feature -- Status
|
|||||||
|
|
||||||
feature -- Helper
|
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'
|
-- Path used by `Current' to check that mapping matches request `req'
|
||||||
require
|
require
|
||||||
req_attached: req /= Void
|
req_attached: req /= Void
|
||||||
do
|
do
|
||||||
Result := req.path_info
|
Result := req.percent_encoded_path_info
|
||||||
ensure
|
ensure
|
||||||
path_from_request_attached: Result /= Void
|
path_from_request_attached: Result /= Void
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ class
|
|||||||
inherit
|
inherit
|
||||||
WSF_SESSION
|
WSF_SESSION
|
||||||
|
|
||||||
|
SHARED_EXECUTION_ENVIRONMENT
|
||||||
|
export
|
||||||
|
{NONE} all
|
||||||
|
end
|
||||||
|
|
||||||
create
|
create
|
||||||
make,
|
make,
|
||||||
make_new
|
make_new
|
||||||
@@ -128,15 +133,6 @@ feature {NONE} -- Storage
|
|||||||
data.compare_objects
|
data.compare_objects
|
||||||
end
|
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
|
load
|
||||||
do
|
do
|
||||||
if manager.session_exists (uuid) then
|
if manager.session_exists (uuid) then
|
||||||
@@ -181,7 +177,7 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ feature {NONE} -- Initialization
|
|||||||
make_with_folder ("_WSF_SESSIONS_")
|
make_with_folder ("_WSF_SESSIONS_")
|
||||||
end
|
end
|
||||||
|
|
||||||
make_with_folder (a_folder: like sessions_folder_name)
|
make_with_folder (a_folder: READABLE_STRING_GENERAL)
|
||||||
do
|
do
|
||||||
sessions_folder_name := a_folder
|
create sessions_folder_name.make_from_string (a_folder)
|
||||||
end
|
end
|
||||||
|
|
||||||
sessions_folder_name: STRING_8
|
sessions_folder_name: PATH
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ feature -- Access
|
|||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
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
|
Result := f.exists and then f.is_readable
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ feature -- Access
|
|||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
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
|
if f.exists and then f.is_readable then
|
||||||
f.open_read
|
f.open_read
|
||||||
if attached data_from_file (f) as d then
|
if attached data_from_file (f) as d then
|
||||||
@@ -68,7 +68,7 @@ feature -- Persistence
|
|||||||
delete_session (a_session)
|
delete_session (a_session)
|
||||||
else
|
else
|
||||||
ensure_session_folder_exists
|
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
|
if not f.exists or else f.is_writable then
|
||||||
f.create_read_write
|
f.create_read_write
|
||||||
a_session.data.set_expiration (a_session.expiration)
|
a_session.data.set_expiration (a_session.expiration)
|
||||||
@@ -91,7 +91,7 @@ feature -- Persistence
|
|||||||
rescued: BOOLEAN
|
rescued: BOOLEAN
|
||||||
do
|
do
|
||||||
if not rescued then
|
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
|
if f.exists then
|
||||||
f.delete
|
f.delete
|
||||||
end
|
end
|
||||||
@@ -131,7 +131,7 @@ feature {NONE} -- Implementation
|
|||||||
local
|
local
|
||||||
d: DIRECTORY
|
d: DIRECTORY
|
||||||
once
|
once
|
||||||
create d.make (sessions_folder_name)
|
create d.make_with_path (sessions_folder_name)
|
||||||
if not d.exists then
|
if not d.exists then
|
||||||
d.recursive_create_dir
|
d.recursive_create_dir
|
||||||
end
|
end
|
||||||
@@ -143,18 +143,13 @@ feature {NONE} -- Implementation
|
|||||||
local
|
local
|
||||||
d: DIRECTORY
|
d: DIRECTORY
|
||||||
do
|
do
|
||||||
create d.make (sessions_folder_name)
|
create d.make_with_path (sessions_folder_name)
|
||||||
Result := d.exists and then d.is_writable
|
Result := d.exists and then d.is_writable
|
||||||
end
|
end
|
||||||
|
|
||||||
file_name (a_uuid: like {WSF_SESSION}.uuid): READABLE_STRING_8
|
file_name (a_uuid: like {WSF_SESSION}.uuid): PATH
|
||||||
local
|
|
||||||
fn: FILE_NAME
|
|
||||||
do
|
do
|
||||||
create fn.make_from_string (sessions_folder_name)
|
Result := sessions_folder_name.extended (a_uuid.out).appended_with_extension ("session")
|
||||||
fn.set_file_name (a_uuid.out)
|
|
||||||
fn.add_extension ("session")
|
|
||||||
Result := fn.string
|
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
note
|
||||||
|
|||||||
@@ -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
|
||||||
523
library/server/wsf/src/implementation/wsf_percent_encoder.e
Normal file
523
library/server/wsf/src/implementation/wsf_percent_encoder.e
Normal file
@@ -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<n> where <n> 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
|
||||||
@@ -62,7 +62,7 @@ feature -- Access
|
|||||||
url_encoded_name: READABLE_STRING_8
|
url_encoded_name: READABLE_STRING_8
|
||||||
-- URL encoded string of `name'.
|
-- URL encoded string of `name'.
|
||||||
do
|
do
|
||||||
Result := url_encoder.encoded_string (name)
|
Result := url_encoded_string (name)
|
||||||
end
|
end
|
||||||
|
|
||||||
values: LIST [WSF_STRING]
|
values: LIST [WSF_STRING]
|
||||||
|
|||||||
@@ -50,20 +50,6 @@ feature -- Access
|
|||||||
url_encoded_value: READABLE_STRING_8
|
url_encoded_value: READABLE_STRING_8
|
||||||
-- URL encoded string of `value'.
|
-- 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
|
feature -- Conversion
|
||||||
|
|
||||||
integer_value: INTEGER
|
integer_value: INTEGER
|
||||||
@@ -137,7 +123,7 @@ feature -- Visitor
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -36,17 +36,17 @@ feature -- Access
|
|||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
debug_output: STRING
|
debug_output: STRING_32
|
||||||
-- String that should be displayed in debugger to represent `Current'.
|
-- String that should be displayed in debugger to represent `Current'.
|
||||||
do
|
do
|
||||||
Result := Precursor
|
Result := Precursor
|
||||||
if
|
if
|
||||||
exists and then
|
exists and then
|
||||||
attached tmp_name as n
|
attached tmp_path as p
|
||||||
then
|
then
|
||||||
Result.append_character (' ')
|
Result.append_character (' ')
|
||||||
Result.append_character ('%"')
|
Result.append_character ('%"')
|
||||||
Result.append (n)
|
Result.append (p.name)
|
||||||
Result.append_character ('%"')
|
Result.append_character ('%"')
|
||||||
end
|
end
|
||||||
Result.append (" filename=%"")
|
Result.append (" filename=%"")
|
||||||
@@ -108,9 +108,16 @@ feature -- Access: Uploaded File
|
|||||||
size: INTEGER
|
size: INTEGER
|
||||||
-- Size of uploaded file
|
-- Size of uploaded file
|
||||||
|
|
||||||
tmp_name: detachable STRING
|
tmp_path: detachable PATH
|
||||||
-- Filename of tmp file
|
-- 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
|
tmp_basename: detachable STRING
|
||||||
-- Basename of tmp file
|
-- Basename of tmp file
|
||||||
|
|
||||||
@@ -237,7 +244,7 @@ feature -- Implementation
|
|||||||
|
|
||||||
feature -- Basic operation
|
feature -- Basic operation
|
||||||
|
|
||||||
move_to (a_destination: STRING): BOOLEAN
|
move_to (a_destination: READABLE_STRING_GENERAL): BOOLEAN
|
||||||
-- Move current uploaded file to `a_destination'
|
-- Move current uploaded file to `a_destination'
|
||||||
--| Violates CQS principle.
|
--| Violates CQS principle.
|
||||||
require
|
require
|
||||||
@@ -246,10 +253,10 @@ feature -- Basic operation
|
|||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
if attached tmp_name as n then
|
if attached tmp_path as p then
|
||||||
create f.make (n)
|
create f.make_with_path (p)
|
||||||
if f.exists then
|
if f.exists then
|
||||||
f.change_name (a_destination)
|
f.rename_file (a_destination)
|
||||||
Result := True
|
Result := True
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -274,8 +281,8 @@ feature -- Status
|
|||||||
local
|
local
|
||||||
f: PLAIN_TEXT_FILE
|
f: PLAIN_TEXT_FILE
|
||||||
do
|
do
|
||||||
if attached tmp_name as n then
|
if attached tmp_path as p then
|
||||||
create f.make (n)
|
create f.make_with_path (p)
|
||||||
Result := f.exists
|
Result := f.exists
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -288,10 +295,19 @@ feature -- Element change
|
|||||||
error := e
|
error := e
|
||||||
end
|
end
|
||||||
|
|
||||||
|
set_tmp_path (p: like tmp_path)
|
||||||
|
do
|
||||||
|
tmp_path := p
|
||||||
|
end
|
||||||
|
|
||||||
set_tmp_name (n: like tmp_name)
|
set_tmp_name (n: like tmp_name)
|
||||||
-- Set `tmp_name' to `n'
|
-- Set `tmp_name' to `n'
|
||||||
do
|
do
|
||||||
tmp_name := n
|
if n /= Void then
|
||||||
|
set_tmp_path (create {PATH}.make_from_string (n))
|
||||||
|
else
|
||||||
|
set_tmp_path (Void)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
set_tmp_basename (n: like tmp_basename)
|
set_tmp_basename (n: like tmp_basename)
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ deferred class
|
|||||||
inherit
|
inherit
|
||||||
DEBUG_OUTPUT
|
DEBUG_OUTPUT
|
||||||
|
|
||||||
|
SHARED_WSF_PERCENT_ENCODER
|
||||||
|
rename
|
||||||
|
percent_encoder as url_encoder
|
||||||
|
export
|
||||||
|
{NONE} all
|
||||||
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
|
|
||||||
name: READABLE_STRING_32
|
name: READABLE_STRING_32
|
||||||
@@ -91,23 +98,26 @@ feature -- Helper
|
|||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
|
|
||||||
debug_output: STRING
|
debug_output: STRING_32
|
||||||
-- String that should be displayed in debugger to represent `Current'.
|
-- String that should be displayed in debugger to represent `Current'.
|
||||||
do
|
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
|
end
|
||||||
|
|
||||||
feature {NONE} -- Implementation
|
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'
|
-- Decoded url-encoded string `s'
|
||||||
do
|
do
|
||||||
Result := url_encoder.decoded_string (s)
|
create Result.make (s.count)
|
||||||
|
url_encoder.append_percent_encoded_string_to (s, Result)
|
||||||
end
|
end
|
||||||
|
|
||||||
url_encoder: URL_ENCODER
|
url_decoded_string (s: READABLE_STRING_GENERAL): STRING_32
|
||||||
once
|
-- Decoded url-encoded string `s'
|
||||||
create {UTF8_URL_ENCODER} Result --| Chrome is UTF-8 encoding the non ascii in query
|
do
|
||||||
|
create Result.make (s.count)
|
||||||
|
url_encoder.append_percent_decoded_string_to (s, Result)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Visitor
|
feature -- Visitor
|
||||||
@@ -117,7 +127,7 @@ feature -- Visitor
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ class
|
|||||||
inherit
|
inherit
|
||||||
WSF_RESPONSE_MESSAGE
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
|
SHARED_UTF8_URL_ENCODER
|
||||||
|
|
||||||
create
|
create
|
||||||
make,
|
make,
|
||||||
make_with_content_type,
|
make_with_content_type,
|
||||||
@@ -17,26 +19,26 @@ create
|
|||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (a_file_name: READABLE_STRING_8)
|
make (a_file_name: READABLE_STRING_GENERAL)
|
||||||
do
|
do
|
||||||
set_status_code ({HTTP_STATUS_CODE}.ok)
|
set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
file_name := a_file_name
|
create file_path.make_from_string (a_file_name)
|
||||||
base_name := basename (a_file_name)
|
base_name := basename (file_path)
|
||||||
get_content_type
|
get_content_type
|
||||||
initialize
|
initialize
|
||||||
end
|
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'.
|
-- Initialize `Current'.
|
||||||
do
|
do
|
||||||
set_status_code ({HTTP_STATUS_CODE}.ok)
|
set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
file_name := a_filename
|
create file_path.make_from_string (a_filename)
|
||||||
base_name := basename (a_filename)
|
base_name := basename (file_path)
|
||||||
content_type := a_content_type
|
content_type := a_content_type
|
||||||
initialize
|
initialize
|
||||||
end
|
end
|
||||||
|
|
||||||
make_html (a_filename: READABLE_STRING_8)
|
make_html (a_filename: READABLE_STRING_GENERAL)
|
||||||
-- Initialize `Current'.
|
-- Initialize `Current'.
|
||||||
do
|
do
|
||||||
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
|
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
|
||||||
@@ -45,15 +47,14 @@ feature {NONE} -- Initialization
|
|||||||
initialize
|
initialize
|
||||||
local
|
local
|
||||||
h: like header
|
h: like header
|
||||||
d: HTTP_DATE
|
|
||||||
do
|
do
|
||||||
create h.make
|
create h.make
|
||||||
header := h
|
header := h
|
||||||
h.put_content_type (content_type)
|
h.put_content_type (content_type)
|
||||||
h.put_transfer_encoding_binary
|
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 +"%"")
|
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)
|
h.put_last_modified (dt)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -89,7 +90,14 @@ feature -- Access
|
|||||||
|
|
||||||
status_code: INTEGER assign set_status_code
|
status_code: INTEGER assign set_status_code
|
||||||
|
|
||||||
|
file_path: PATH
|
||||||
|
|
||||||
file_name: READABLE_STRING_8
|
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
|
base_name: READABLE_STRING_8
|
||||||
|
|
||||||
@@ -125,73 +133,57 @@ feature {WSF_RESPONSE} -- Output
|
|||||||
res.set_status_code (status_code)
|
res.set_status_code (status_code)
|
||||||
res.put_header_text (header.string)
|
res.put_header_text (header.string)
|
||||||
if not answer_head_request_method then
|
if not answer_head_request_method then
|
||||||
send_file_content_to (file_name, res)
|
send_file_content_to (file_path, res)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Implementation: file system helper
|
feature {NONE} -- Implementation: file system helper
|
||||||
|
|
||||||
filesize (fn: STRING): INTEGER
|
filesize (fn: PATH): INTEGER
|
||||||
-- Size of the file `fn'.
|
-- Size of the file `fn'.
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
if f.exists then
|
if f.exists then
|
||||||
Result := f.count
|
Result := f.count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
filedate (fn: STRING): detachable DATE_TIME
|
filedate (fn: PATH): detachable DATE_TIME
|
||||||
-- Size of the file `fn'.
|
-- Size of the file `fn'.
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
d: HTTP_DATE
|
d: HTTP_DATE
|
||||||
do
|
do
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
if f.exists then
|
if f.exists then
|
||||||
create d.make_from_timestamp (f.date)
|
create d.make_from_timestamp (f.date)
|
||||||
Result := d.date_time
|
Result := d.date_time
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
file_extension (fn: STRING): STRING
|
file_extension (fn: PATH): STRING_32
|
||||||
-- Extension of file `fn'.
|
-- Extension of file `fn'.
|
||||||
local
|
|
||||||
p: INTEGER
|
|
||||||
do
|
do
|
||||||
p := fn.last_index_of ('.', fn.count)
|
if attached fn.extension as ext then
|
||||||
if p > 0 then
|
Result := ext
|
||||||
Result := fn.substring (p + 1, fn.count)
|
|
||||||
else
|
else
|
||||||
create Result.make_empty
|
create Result.make_empty
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
basename (fn: STRING): STRING
|
basename (fn: PATH): STRING
|
||||||
-- Basename of `fn'.
|
-- Basename of `fn'.
|
||||||
local
|
local
|
||||||
p: INTEGER
|
s: READABLE_STRING_32
|
||||||
do
|
do
|
||||||
p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
|
if attached fn.entry as p then
|
||||||
if p > 0 then
|
s := p.name
|
||||||
Result := fn.substring (p + 1, fn.count)
|
|
||||||
else
|
else
|
||||||
Result := fn
|
s := fn.name
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
Result := url_encoder.encoded_string (s)
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Content-type related
|
feature -- Content-type related
|
||||||
@@ -203,7 +195,7 @@ feature -- Content-type related
|
|||||||
m: detachable READABLE_STRING_8
|
m: detachable READABLE_STRING_8
|
||||||
do
|
do
|
||||||
create m_map.make_default
|
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
|
if m = Void then
|
||||||
m := {HTTP_MIME_TYPES}.application_force_download
|
m := {HTTP_MIME_TYPES}.application_force_download
|
||||||
end
|
end
|
||||||
@@ -212,15 +204,15 @@ feature -- Content-type related
|
|||||||
|
|
||||||
feature -- Implementation: output
|
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'
|
-- Send the content of file `fn'
|
||||||
require
|
require
|
||||||
string_not_empty: not fn.is_empty
|
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
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
check f.exists and then f.is_readable end
|
check f.exists and then f.is_readable end
|
||||||
|
|
||||||
f.open_read
|
f.open_read
|
||||||
|
|||||||
@@ -11,30 +11,49 @@ inherit
|
|||||||
WSF_RESPONSE_MESSAGE
|
WSF_RESPONSE_MESSAGE
|
||||||
|
|
||||||
create
|
create
|
||||||
|
make_with_path,
|
||||||
|
make_with_content_type_and_path,
|
||||||
|
make_html_with_path,
|
||||||
make,
|
make,
|
||||||
make_with_content_type,
|
make_with_content_type,
|
||||||
make_html
|
make_html
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make (a_file_name: READABLE_STRING_8)
|
make_with_path (a_path: PATH)
|
||||||
do
|
do
|
||||||
set_status_code ({HTTP_STATUS_CODE}.ok)
|
set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
file_name := a_file_name
|
file_path := a_path
|
||||||
get_content_type
|
get_content_type
|
||||||
initialize
|
initialize
|
||||||
end
|
end
|
||||||
|
|
||||||
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
|
make_with_content_type_and_path (a_content_type: READABLE_STRING_8; a_path: PATH)
|
||||||
-- Initialize `Current'.
|
|
||||||
do
|
do
|
||||||
set_status_code ({HTTP_STATUS_CODE}.ok)
|
set_status_code ({HTTP_STATUS_CODE}.ok)
|
||||||
file_name := a_filename
|
file_path := a_path
|
||||||
content_type := a_content_type
|
content_type := a_content_type
|
||||||
initialize
|
initialize
|
||||||
end
|
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'.
|
-- Initialize `Current'.
|
||||||
do
|
do
|
||||||
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
|
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
|
||||||
@@ -118,13 +137,21 @@ feature -- Access
|
|||||||
content_type: READABLE_STRING_8
|
content_type: READABLE_STRING_8
|
||||||
-- Content-Type of the response
|
-- Content-Type of the response
|
||||||
|
|
||||||
|
file_path: path
|
||||||
|
-- File path
|
||||||
|
|
||||||
file_name: READABLE_STRING_8
|
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: BOOLEAN
|
||||||
-- File exists?
|
-- File exists?
|
||||||
|
|
||||||
file_size: INTEGER
|
file_size: INTEGER
|
||||||
-- Size of file named `file_name'
|
-- Size of file `file_path'
|
||||||
|
|
||||||
head, bottom: detachable READABLE_STRING_8
|
head, bottom: detachable READABLE_STRING_8
|
||||||
-- Eventual head and bottom part
|
-- Eventual head and bottom part
|
||||||
@@ -184,7 +211,7 @@ feature {WSF_RESPONSE} -- Output
|
|||||||
res.put_string (s)
|
res.put_string (s)
|
||||||
end
|
end
|
||||||
if not answer_head_request_method then
|
if not answer_head_request_method then
|
||||||
send_file_content_to (file_name, res)
|
send_file_content_to (file_path, res)
|
||||||
end
|
end
|
||||||
s := bottom
|
s := bottom
|
||||||
if s /= Void then
|
if s /= Void then
|
||||||
@@ -200,40 +227,37 @@ feature {NONE} -- Implementation: file system helper
|
|||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (file_name)
|
create f.make_with_path (file_path)
|
||||||
file_exists := f.exists
|
file_exists := f.exists
|
||||||
end
|
end
|
||||||
|
|
||||||
get_file_size
|
get_file_size
|
||||||
-- Get `file_size' from file named `file_name'
|
-- Get `file_size' from file named `file_path'
|
||||||
require
|
require
|
||||||
file_exists: file_exists
|
file_exists: file_exists
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (file_name)
|
create f.make_with_path (file_path)
|
||||||
file_size := f.count
|
file_size := f.count
|
||||||
end
|
end
|
||||||
|
|
||||||
file_last_modified: detachable DATE_TIME
|
file_last_modified: detachable DATE_TIME
|
||||||
-- Get `file_size' from file named `file_name'
|
-- Get `file_size' from file named `file_path'
|
||||||
require
|
require
|
||||||
file_exists: file_exists
|
file_exists: file_exists
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (file_name)
|
create f.make_with_path (file_path)
|
||||||
create Result.make_from_epoch (f.change_date)
|
create Result.make_from_epoch (f.change_date)
|
||||||
end
|
end
|
||||||
|
|
||||||
file_extension (fn: STRING): STRING
|
file_extension (fn: PATH): STRING_32
|
||||||
-- Extension of file `fn'.
|
-- Extension of file `fn'.
|
||||||
local
|
|
||||||
p: INTEGER
|
|
||||||
do
|
do
|
||||||
p := fn.last_index_of ('.', fn.count)
|
if attached fn.extension as ext then
|
||||||
if p > 0 then
|
Result := ext
|
||||||
Result := fn.substring (p + 1, fn.count)
|
|
||||||
else
|
else
|
||||||
create Result.make_empty
|
create Result.make_empty
|
||||||
end
|
end
|
||||||
@@ -242,13 +266,13 @@ feature {NONE} -- Implementation: file system helper
|
|||||||
feature -- Content-type related
|
feature -- Content-type related
|
||||||
|
|
||||||
get_content_type
|
get_content_type
|
||||||
-- Content type associated with `file_name'
|
-- Content type associated with `file_path'
|
||||||
local
|
local
|
||||||
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
|
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
|
||||||
m: detachable READABLE_STRING_8
|
m: detachable READABLE_STRING_8
|
||||||
do
|
do
|
||||||
create m_map.make_default
|
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
|
if m = Void then
|
||||||
m := {HTTP_MIME_TYPES}.application_force_download
|
m := {HTTP_MIME_TYPES}.application_force_download
|
||||||
end
|
end
|
||||||
@@ -257,16 +281,16 @@ feature -- Content-type related
|
|||||||
|
|
||||||
feature {NONE} -- Implementation: output
|
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'
|
-- Send the content of file `fn'
|
||||||
require
|
require
|
||||||
string_not_empty: not fn.is_empty
|
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
|
file_exists: file_exists
|
||||||
local
|
local
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
check f.is_readable end
|
check f.is_readable end
|
||||||
|
|
||||||
f.open_read
|
f.open_read
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class
|
|||||||
WSF_SERVICE_LAUNCHER_OPTIONS
|
WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
|
|
||||||
inherit
|
inherit
|
||||||
ANY
|
TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]
|
||||||
redefine
|
redefine
|
||||||
default_create
|
default_create
|
||||||
end
|
end
|
||||||
@@ -23,7 +23,8 @@ inherit
|
|||||||
create
|
create
|
||||||
default_create,
|
default_create,
|
||||||
make,
|
make,
|
||||||
make_from_array
|
make_from_array,
|
||||||
|
make_from_iterable
|
||||||
|
|
||||||
convert
|
convert
|
||||||
make_from_array ({ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]})
|
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]])
|
make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
|
||||||
do
|
do
|
||||||
make
|
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
|
across
|
||||||
a_options as opt
|
a_options as opt
|
||||||
loop
|
loop
|
||||||
@@ -53,6 +67,15 @@ feature {NONE} -- Initialization
|
|||||||
end
|
end
|
||||||
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
|
feature -- Access
|
||||||
|
|
||||||
option (a_name: READABLE_STRING_GENERAL): detachable ANY
|
option (a_name: READABLE_STRING_GENERAL): detachable ANY
|
||||||
@@ -60,6 +83,14 @@ feature -- Access
|
|||||||
Result := options.item (a_name)
|
Result := options.item (a_name)
|
||||||
end
|
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
|
feature -- Element change
|
||||||
|
|
||||||
set_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
|
set_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
|
||||||
@@ -75,13 +106,13 @@ feature -- Element change
|
|||||||
|
|
||||||
feature {NONE} -- Implementation
|
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
|
-- Custom options which might be support (or not) by the default service
|
||||||
|
|
||||||
invariant
|
invariant
|
||||||
options_attached: options /= Void
|
options_attached: options /= Void
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -11,28 +11,40 @@ inherit
|
|||||||
WSF_SERVICE_LAUNCHER_OPTIONS
|
WSF_SERVICE_LAUNCHER_OPTIONS
|
||||||
|
|
||||||
create
|
create
|
||||||
make_from_file
|
make_from_file,
|
||||||
|
make_from_file_and_defaults
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
feature {NONE} -- Initialization
|
||||||
|
|
||||||
make_from_file (a_filename: READABLE_STRING_32)
|
make_from_file (a_filename: READABLE_STRING_GENERAL)
|
||||||
-- Initialize `Current'.
|
-- Initialize `Current'.
|
||||||
do
|
do
|
||||||
make
|
make
|
||||||
import (a_filename)
|
import (a_filename)
|
||||||
end
|
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
|
feature {NONE} -- Implementation
|
||||||
|
|
||||||
import (a_filename: READABLE_STRING_32)
|
import (a_filename: READABLE_STRING_GENERAL)
|
||||||
-- Import ini file content
|
-- Import ini file content
|
||||||
local
|
local
|
||||||
f: PLAIN_TEXT_FILE
|
f: PLAIN_TEXT_FILE
|
||||||
l,v: STRING_8
|
l,v: STRING_8
|
||||||
p: INTEGER
|
p: INTEGER
|
||||||
do
|
do
|
||||||
--FIXME: handle unicode filename here.
|
create f.make_with_name (a_filename)
|
||||||
create f.make (a_filename)
|
|
||||||
if f.exists and f.is_readable then
|
if f.exists and f.is_readable then
|
||||||
f.open_read
|
f.open_read
|
||||||
from
|
from
|
||||||
@@ -60,7 +72,7 @@ feature {NONE} -- Implementation
|
|||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -26,6 +26,18 @@ class
|
|||||||
inherit
|
inherit
|
||||||
DEBUG_OUTPUT
|
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}
|
create {WSF_TO_WGI_SERVICE}
|
||||||
make_from_wgi
|
make_from_wgi
|
||||||
|
|
||||||
@@ -40,26 +52,25 @@ feature {NONE} -- Initialization
|
|||||||
do
|
do
|
||||||
wgi_request := r
|
wgi_request := r
|
||||||
|
|
||||||
create string_equality_tester
|
|
||||||
if attached r.meta_variables as l_vars then
|
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
|
across
|
||||||
l_vars as c
|
l_vars as c
|
||||||
loop
|
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
|
end
|
||||||
else
|
else
|
||||||
create tb.make_with_key_tester (0, string_equality_tester)
|
create tb.make_equal (0)
|
||||||
end
|
end
|
||||||
meta_variables_table := tb
|
meta_variables_table := tb
|
||||||
meta_variables := tb
|
|
||||||
create error_handler.make
|
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)
|
set_raw_input_data_recorded (False)
|
||||||
create {IMMUTABLE_STRING_32} empty_string.make_empty
|
create execution_variables_table.make_equal (0)
|
||||||
|
|
||||||
create execution_variables_table.make_with_key_tester (0, string_equality_tester)
|
|
||||||
execution_variables_table.compare_objects
|
|
||||||
|
|
||||||
initialize
|
initialize
|
||||||
analyze
|
analyze
|
||||||
@@ -96,12 +107,13 @@ feature {NONE} -- Initialization
|
|||||||
request_method := req.request_method
|
request_method := req.request_method
|
||||||
|
|
||||||
--| PATH_INFO
|
--| 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
|
--| PATH_TRANSLATED
|
||||||
s8 := req.path_translated
|
s8 := req.path_translated
|
||||||
if s8 /= Void then
|
if s8 /= Void then
|
||||||
path_translated := raw_url_encoder.decoded_string (s8)
|
path_translated := url_decoded_string (s8)
|
||||||
end
|
end
|
||||||
|
|
||||||
--| Here one can set its own environment entries if needed
|
--| Here one can set its own environment entries if needed
|
||||||
@@ -111,6 +123,7 @@ feature {NONE} -- Initialization
|
|||||||
end
|
end
|
||||||
|
|
||||||
wgi_request: WGI_REQUEST
|
wgi_request: WGI_REQUEST
|
||||||
|
-- Associated WGI request
|
||||||
|
|
||||||
feature -- Destroy
|
feature -- Destroy
|
||||||
|
|
||||||
@@ -125,6 +138,26 @@ feature -- Destroy
|
|||||||
loop
|
loop
|
||||||
delete_uploaded_file (c.item)
|
delete_uploaded_file (c.item)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
feature -- Status report
|
feature -- Status report
|
||||||
@@ -353,12 +386,12 @@ feature {WSF_REQUEST_EXPORTER} -- Override value
|
|||||||
|
|
||||||
feature {NONE} -- Access: global variable
|
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
|
-- Table containing all the various variables
|
||||||
-- Warning: this is computed each time, if you change the content of other containers
|
-- 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
|
-- this won't update this Result's content, unless you query it again
|
||||||
do
|
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
|
if attached path_parameters as l_path_parameters then
|
||||||
across
|
across
|
||||||
@@ -558,7 +591,7 @@ feature -- Execution variables
|
|||||||
|
|
||||||
feature {NONE} -- Execution variables: implementation
|
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
|
feature -- Access: CGI Meta variables
|
||||||
|
|
||||||
@@ -582,6 +615,9 @@ feature -- Access: CGI Meta variables
|
|||||||
|
|
||||||
meta_variables: ITERABLE [WSF_STRING]
|
meta_variables: ITERABLE [WSF_STRING]
|
||||||
-- CGI meta variables values
|
-- 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
|
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'
|
-- Value for meta parameter `a_name'
|
||||||
@@ -617,7 +653,7 @@ feature -- Access: CGI Meta variables
|
|||||||
|
|
||||||
feature {NONE} -- Access: CGI meta parameters
|
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
|
-- CGI Environment parameters
|
||||||
|
|
||||||
feature -- Access: CGI meta parameters - 1.1
|
feature -- Access: CGI meta parameters - 1.1
|
||||||
@@ -739,6 +775,11 @@ feature -- Access: CGI meta parameters - 1.1
|
|||||||
Result := wgi_request.gateway_interface
|
Result := wgi_request.gateway_interface
|
||||||
end
|
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
|
path_info: READABLE_STRING_32
|
||||||
-- The PATH_INFO metavariable specifies a path to be interpreted
|
-- The PATH_INFO metavariable specifies a path to be interpreted
|
||||||
-- by the CGI script. It identifies the resource or sub-resource
|
-- 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
|
-- The PATH_INFO value is case-sensitive, and the server MUST
|
||||||
-- preserve the case of the PATH_INFO element of the URI when
|
-- preserve the case of the PATH_INFO element of the URI when
|
||||||
-- making it available to scripts.
|
-- 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: detachable READABLE_STRING_32
|
||||||
-- PATH_TRANSLATED is derived by taking any path-info component
|
-- PATH_TRANSLATED is derived by taking any path-info component
|
||||||
@@ -1150,7 +1193,7 @@ feature -- Cookies
|
|||||||
|
|
||||||
feature {NONE} -- Cookies
|
feature {NONE} -- Cookies
|
||||||
|
|
||||||
cookies_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
|
cookies_table: STRING_TABLE [WSF_VALUE]
|
||||||
-- Expanded cookies variable
|
-- Expanded cookies variable
|
||||||
local
|
local
|
||||||
i,j,p,n: INTEGER
|
i,j,p,n: INTEGER
|
||||||
@@ -1161,8 +1204,7 @@ feature {NONE} -- Cookies
|
|||||||
if l_cookies = Void then
|
if l_cookies = Void then
|
||||||
if attached {WSF_STRING} meta_variable ({WSF_META_NAMES}.http_cookie) as val then
|
if attached {WSF_STRING} meta_variable ({WSF_META_NAMES}.http_cookie) as val then
|
||||||
s := val.value
|
s := val.value
|
||||||
create l_cookies.make_with_key_tester (5, string_equality_tester)
|
create l_cookies.make_equal (5)
|
||||||
l_cookies.compare_objects
|
|
||||||
from
|
from
|
||||||
n := s.count
|
n := s.count
|
||||||
p := 1
|
p := 1
|
||||||
@@ -1190,8 +1232,7 @@ feature {NONE} -- Cookies
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
create l_cookies.make_with_key_tester (0, string_equality_tester)
|
create l_cookies.make_equal (0)
|
||||||
l_cookies.compare_objects
|
|
||||||
end
|
end
|
||||||
internal_cookies_table := l_cookies
|
internal_cookies_table := l_cookies
|
||||||
end
|
end
|
||||||
@@ -1217,7 +1258,7 @@ feature -- Path parameters
|
|||||||
|
|
||||||
feature {NONE} -- Query parameters: implementation
|
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'
|
-- Parameters computed from `path_parameters_source'
|
||||||
--| most often coming from the associated route from WSF_ROUTER
|
--| 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
|
if l_count = 0 then
|
||||||
l_table := Void
|
l_table := Void
|
||||||
else
|
else
|
||||||
create l_table.make_with_key_tester (l_count, string_equality_tester)
|
create l_table.make_equal (l_count)
|
||||||
l_table.compare_objects
|
|
||||||
if attached src.path_parameters as tb then
|
if attached src.path_parameters as tb then
|
||||||
across
|
across
|
||||||
tb as c
|
tb as c
|
||||||
@@ -1278,7 +1318,7 @@ feature -- Query parameters
|
|||||||
|
|
||||||
feature {NONE} -- Query parameters: implementation
|
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
|
-- Parameters extracted from QUERY_STRING
|
||||||
local
|
local
|
||||||
vars: like internal_query_parameters_table
|
vars: like internal_query_parameters_table
|
||||||
@@ -1303,13 +1343,12 @@ feature {NONE} -- Query parameters: implementation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
vars := urlencoded_parameters (s)
|
vars := urlencoded_parameters (s)
|
||||||
vars.compare_objects
|
|
||||||
internal_query_parameters_table := vars
|
internal_query_parameters_table := vars
|
||||||
end
|
end
|
||||||
Result := vars
|
Result := vars
|
||||||
end
|
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'
|
-- Import `a_content'
|
||||||
local
|
local
|
||||||
n, p, i, j: INTEGER
|
n, p, i, j: INTEGER
|
||||||
@@ -1317,13 +1356,13 @@ feature {NONE} -- Query parameters: implementation
|
|||||||
l_name, l_value: READABLE_STRING_8
|
l_name, l_value: READABLE_STRING_8
|
||||||
do
|
do
|
||||||
if a_content = Void then
|
if a_content = Void then
|
||||||
create Result.make_with_key_tester (0, string_equality_tester)
|
create Result.make_equal (0)
|
||||||
else
|
else
|
||||||
n := a_content.count
|
n := a_content.count
|
||||||
if n = 0 then
|
if n = 0 then
|
||||||
create Result.make_with_key_tester (0, string_equality_tester)
|
create Result.make_equal (0)
|
||||||
else
|
else
|
||||||
create Result.make_with_key_tester (3, string_equality_tester) --| 3 = arbitrary value
|
create Result.make_equal (3) --| 3 = arbitrary value
|
||||||
from
|
from
|
||||||
p := 1
|
p := 1
|
||||||
until
|
until
|
||||||
@@ -1348,6 +1387,8 @@ feature {NONE} -- Query parameters: implementation
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
ensure
|
||||||
|
result_with_object_comparison: Result.object_comparison
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Form fields and related
|
feature -- Form fields and related
|
||||||
@@ -1452,7 +1493,7 @@ feature {NONE} -- Implementation: MIME handler
|
|||||||
|
|
||||||
feature {NONE} -- Form fields and related
|
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
|
get_form_parameters
|
||||||
-- Variables sent by POST, ... request
|
-- Variables sent by POST, ... request
|
||||||
@@ -1464,14 +1505,12 @@ feature {NONE} -- Form fields and related
|
|||||||
vars := internal_form_data_parameters_table
|
vars := internal_form_data_parameters_table
|
||||||
if vars = Void then
|
if vars = Void then
|
||||||
if not is_chunked_input and content_length_value = 0 then
|
if not is_chunked_input and content_length_value = 0 then
|
||||||
create vars.make_with_key_tester (0, string_equality_tester)
|
create vars.make_equal (0)
|
||||||
vars.compare_objects
|
|
||||||
else
|
else
|
||||||
if raw_input_data_recorded then
|
if raw_input_data_recorded then
|
||||||
create l_raw_data_cell.put (Void)
|
create l_raw_data_cell.put (Void)
|
||||||
end
|
end
|
||||||
create vars.make_with_key_tester (5, string_equality_tester)
|
create vars.make_equal (5)
|
||||||
vars.compare_objects
|
|
||||||
|
|
||||||
l_type := content_type
|
l_type := content_type
|
||||||
if l_type /= Void and then attached mime_handler (l_type) as hdl then
|
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
|
internal_form_data_parameters_table /= Void
|
||||||
end
|
end
|
||||||
|
|
||||||
form_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
|
form_parameters_table: STRING_TABLE [WSF_VALUE]
|
||||||
-- Variables sent by POST request
|
-- Variables sent by POST request
|
||||||
local
|
local
|
||||||
vars: like internal_form_data_parameters_table
|
vars: like internal_form_data_parameters_table
|
||||||
@@ -1497,14 +1536,14 @@ feature {NONE} -- Form fields and related
|
|||||||
vars := internal_form_data_parameters_table
|
vars := internal_form_data_parameters_table
|
||||||
if vars = Void then
|
if vars = Void then
|
||||||
check form_parameters_already_retrieved: False end
|
check form_parameters_already_retrieved: False end
|
||||||
create vars.make_with_key_tester (0, string_equality_tester)
|
create vars.make_equal (0)
|
||||||
end
|
end
|
||||||
Result := vars
|
Result := vars
|
||||||
end
|
end
|
||||||
|
|
||||||
feature {NONE} -- Implementation: smart parameter identification
|
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'
|
-- Add urlencoded parameter `a_name'=`a_value' to `a_table'
|
||||||
-- following smart computation such as handling the "..[..]" as table
|
-- following smart computation such as handling the "..[..]" as table
|
||||||
local
|
local
|
||||||
@@ -1548,7 +1587,7 @@ feature {NONE} -- Implementation: smart parameter identification
|
|||||||
if p > 0 then
|
if p > 0 then
|
||||||
q := r.index_of ({CHARACTER_8} ']', p + 1)
|
q := r.index_of ({CHARACTER_8} ']', p + 1)
|
||||||
if q > p then
|
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
|
if attached {WSF_TABLE} ptb.value (k32) as l_tb_value then
|
||||||
tb := l_tb_value
|
tb := l_tb_value
|
||||||
else
|
else
|
||||||
@@ -1610,7 +1649,7 @@ feature -- Uploaded File Handling
|
|||||||
until
|
until
|
||||||
l_files.after or Result
|
l_files.after or Result
|
||||||
loop
|
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
|
Result := True
|
||||||
end
|
end
|
||||||
l_files.forth
|
l_files.forth
|
||||||
@@ -1686,7 +1725,7 @@ feature -- URL Utility
|
|||||||
elseif spos > 0 then
|
elseif spos > 0 then
|
||||||
i := spos
|
i := spos
|
||||||
end
|
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
|
if spos > 0 then
|
||||||
l_base_url := l_rq_uri.substring (1, spos - 1)
|
l_base_url := l_rq_uri.substring (1, spos - 1)
|
||||||
else
|
else
|
||||||
@@ -1736,18 +1775,18 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
|
|||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
do
|
do
|
||||||
if uploaded_files_table.has_item (uf) then
|
if uploaded_files_table.has_item (uf) then
|
||||||
if attached uf.tmp_name as fn then
|
if attached uf.tmp_path as fn then
|
||||||
create f.make (fn)
|
create f.make_with_path (fn)
|
||||||
if f.exists and then f.is_writable then
|
if f.exists and then f.is_writable then
|
||||||
f.delete
|
f.delete
|
||||||
else
|
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
|
end
|
||||||
else
|
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
|
end
|
||||||
else
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1757,8 +1796,8 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
|
|||||||
bn: STRING
|
bn: STRING
|
||||||
l_safe_name: STRING
|
l_safe_name: STRING
|
||||||
f: RAW_FILE
|
f: RAW_FILE
|
||||||
dn: STRING
|
dn: PATH
|
||||||
fn: FILE_NAME
|
fn: PATH
|
||||||
d: DIRECTORY
|
d: DIRECTORY
|
||||||
n: INTEGER
|
n: INTEGER
|
||||||
rescued: BOOLEAN
|
rescued: BOOLEAN
|
||||||
@@ -1768,30 +1807,28 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
|
|||||||
dn := p
|
dn := p
|
||||||
else
|
else
|
||||||
-- FIXME: should it be configured somewhere?
|
-- FIXME: should it be configured somewhere?
|
||||||
dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory
|
dn := execution_environment.current_working_path
|
||||||
end
|
end
|
||||||
create d.make (dn)
|
create d.make_with_path (dn)
|
||||||
if d.exists and then d.is_writable then
|
if d.exists and then d.is_writable then
|
||||||
l_safe_name := a_up_file.safe_filename
|
l_safe_name := a_up_file.safe_filename
|
||||||
from
|
from
|
||||||
create fn.make_from_string (dn)
|
bn := "tmp-" + l_safe_name
|
||||||
bn := "EWF_tmp-" + l_safe_name
|
fn := dn.extended (bn)
|
||||||
fn.set_file_name (bn)
|
create f.make_with_path (fn)
|
||||||
create f.make (fn.string)
|
|
||||||
n := 0
|
n := 0
|
||||||
until
|
until
|
||||||
not f.exists
|
not f.exists
|
||||||
or else n > 1_000
|
or else n > 1_000
|
||||||
loop
|
loop
|
||||||
n := n + 1
|
n := n + 1
|
||||||
fn.make_from_string (dn)
|
bn := "tmp-" + n.out + "-" + l_safe_name
|
||||||
bn := "EWF_tmp-" + n.out + "-" + l_safe_name
|
fn := dn.extended (bn)
|
||||||
fn.set_file_name (bn)
|
f.make_with_path (fn)
|
||||||
f.make (fn.string)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not f.exists or else f.is_writable then
|
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)
|
a_up_file.set_tmp_basename (bn)
|
||||||
f.open_write
|
f.open_write
|
||||||
f.put_string (a_content)
|
f.put_string (a_content)
|
||||||
@@ -1800,7 +1837,7 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
|
|||||||
a_up_file.set_error (-1)
|
a_up_file.set_error (-1)
|
||||||
end
|
end
|
||||||
else
|
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
|
end
|
||||||
uploaded_files_table.force (a_up_file, a_up_file.name)
|
uploaded_files_table.force (a_up_file, a_up_file.name)
|
||||||
else
|
else
|
||||||
@@ -1813,13 +1850,13 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
|
|||||||
|
|
||||||
feature {WSF_REQUEST_EXPORTER} -- Settings
|
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
|
-- Optional folder path used to store uploaded files
|
||||||
|
|
||||||
set_uploaded_file_path (p: like uploaded_file_path)
|
set_uploaded_file_path (p: like uploaded_file_path)
|
||||||
-- Set `uploaded_file_path' to `p'.
|
-- Set `uploaded_file_path' to `p'.
|
||||||
require
|
require
|
||||||
path_exists: p /= Void implies (create {DIRECTORY}.make (p)).exists
|
path_exists: p /= Void implies (create {DIRECTORY}.make_with_path (p)).exists
|
||||||
do
|
do
|
||||||
uploaded_file_path := p
|
uploaded_file_path := p
|
||||||
end
|
end
|
||||||
@@ -1874,8 +1911,6 @@ feature {NONE} -- Implementation
|
|||||||
|
|
||||||
feature {NONE} -- Implementation: utilities
|
feature {NONE} -- Implementation: utilities
|
||||||
|
|
||||||
string_equality_tester: STRING_EQUALITY_TESTER
|
|
||||||
|
|
||||||
single_slash_starting_string (s: READABLE_STRING_32): STRING_32
|
single_slash_starting_string (s: READABLE_STRING_32): STRING_32
|
||||||
-- Return the string `s' (or twin) with one and only one starting slash
|
-- Return the string `s' (or twin) with one and only one starting slash
|
||||||
local
|
local
|
||||||
@@ -1927,17 +1962,27 @@ feature {NONE} -- Implementation: utilities
|
|||||||
create Result.make (a_name, a_value)
|
create Result.make (a_name, a_value)
|
||||||
end
|
end
|
||||||
|
|
||||||
empty_string: READABLE_STRING_32
|
empty_string_32: IMMUTABLE_STRING_32
|
||||||
-- Reusable empty string
|
-- Reusable empty string
|
||||||
|
|
||||||
raw_url_encoder: URL_ENCODER
|
|
||||||
once
|
once
|
||||||
create {URL_ENCODER} Result
|
create Result.make_empty
|
||||||
end
|
end
|
||||||
|
|
||||||
url_encoder: URL_ENCODER
|
empty_string_8: IMMUTABLE_STRING_8
|
||||||
once
|
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
|
end
|
||||||
|
|
||||||
date_time_utilities: HTTP_DATE_TIME_UTILITIES
|
date_time_utilities: HTTP_DATE_TIME_UTILITIES
|
||||||
@@ -1947,7 +1992,8 @@ feature {NONE} -- Implementation: utilities
|
|||||||
end
|
end
|
||||||
|
|
||||||
invariant
|
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
|
wgi_request.content_type /= Void implies content_type /= Void
|
||||||
|
|
||||||
note
|
note
|
||||||
|
|||||||
@@ -11,22 +11,10 @@
|
|||||||
<assertions precondition="true"/>
|
<assertions precondition="true"/>
|
||||||
</option>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||||
<library name="encoding" location="$ISE_LIBRARY\library\encoding\encoding-safe.ecf"/>
|
|
||||||
<cluster name="src" location="src\" recursive="true">
|
<cluster name="src" location="src\" recursive="true">
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>/tests$</exclude>
|
<exclude>/tests$</exclude>
|
||||||
<exclude>/spec$</exclude>
|
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<cluster name="src_before_70" location="$|spec\before_70\" recursive="true">
|
|
||||||
<condition>
|
|
||||||
<version type="compiler" max="7.0.8.7585"/>
|
|
||||||
</condition>
|
|
||||||
</cluster>
|
|
||||||
<cluster name="src_70" location="$|spec\70\" recursive="true">
|
|
||||||
<condition>
|
|
||||||
<version type="compiler" min="7.0.8.7586"/>
|
|
||||||
</condition>
|
|
||||||
</cluster>
|
|
||||||
</cluster>
|
</cluster>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -11,22 +11,10 @@
|
|||||||
<assertions precondition="true"/>
|
<assertions precondition="true"/>
|
||||||
</option>
|
</option>
|
||||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||||
<library name="encoding" location="$ISE_LIBRARY\library\encoding\encoding.ecf"/>
|
|
||||||
<cluster name="src" location="src\" recursive="true">
|
<cluster name="src" location="src\" recursive="true">
|
||||||
<file_rule>
|
<file_rule>
|
||||||
<exclude>/tests$</exclude>
|
<exclude>/tests$</exclude>
|
||||||
<exclude>/spec$</exclude>
|
|
||||||
</file_rule>
|
</file_rule>
|
||||||
<cluster name="src_before_70" location="$\spec\before_70" recursive="true">
|
|
||||||
<condition>
|
|
||||||
<version type="compiler" max="7.0.8.7585"/>
|
|
||||||
</condition>
|
|
||||||
</cluster>
|
|
||||||
<cluster name="src_70" location="$\spec\70" recursive="true">
|
|
||||||
<condition>
|
|
||||||
<version type="compiler" min="7.0.8.7586"/>
|
|
||||||
</condition>
|
|
||||||
</cluster>
|
|
||||||
</cluster>
|
</cluster>
|
||||||
</target>
|
</target>
|
||||||
</system>
|
</system>
|
||||||
|
|||||||
@@ -1,26 +1,21 @@
|
|||||||
note
|
note
|
||||||
description : "Objects that ..."
|
description: "Objects to access the shared once UTF8_URL_ENCODER ..."
|
||||||
author : "$Author$"
|
date: "$Date$"
|
||||||
date : "$Date$"
|
revision: "$Revision$"
|
||||||
revision : "$Revision$"
|
|
||||||
|
|
||||||
deferred class
|
class
|
||||||
UTF8_ENCODER_HELPER
|
SHARED_UTF8_URL_ENCODER
|
||||||
|
|
||||||
inherit
|
feature -- Encoder
|
||||||
ANY
|
|
||||||
|
|
||||||
UNICODE_CONVERSION
|
url_encoder: UTF8_URL_ENCODER
|
||||||
export
|
-- Shared UTF8 URL encoder.
|
||||||
{NONE} all
|
once
|
||||||
{ANY} is_valid_utf8
|
create Result
|
||||||
undefine
|
|
||||||
is_little_endian
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
@@ -29,4 +24,5 @@ note
|
|||||||
Website http://www.eiffel.com
|
Website http://www.eiffel.com
|
||||||
Customer support http://support.eiffel.com
|
Customer support http://support.eiffel.com
|
||||||
]"
|
]"
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -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
|
|
||||||
@@ -15,8 +15,6 @@ class
|
|||||||
inherit
|
inherit
|
||||||
ENCODER [READABLE_STRING_32, READABLE_STRING_8]
|
ENCODER [READABLE_STRING_32, READABLE_STRING_8]
|
||||||
|
|
||||||
UTF8_ENCODER_HELPER
|
|
||||||
|
|
||||||
PLATFORM
|
PLATFORM
|
||||||
export
|
export
|
||||||
{NONE} all
|
{NONE} all
|
||||||
@@ -37,9 +35,13 @@ feature -- Encoder
|
|||||||
|
|
||||||
encoded_string (s: READABLE_STRING_32): STRING_8
|
encoded_string (s: READABLE_STRING_32): STRING_8
|
||||||
-- UTF8-encoded value of `s'.
|
-- UTF8-encoded value of `s'.
|
||||||
|
do
|
||||||
|
Result := general_encoded_string (s)
|
||||||
|
end
|
||||||
|
|
||||||
|
general_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
|
||||||
do
|
do
|
||||||
Result := utf32_to_utf8 (s)
|
Result := utf32_to_utf8 (s)
|
||||||
has_error := not last_conversion_successful
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Decoder
|
feature -- Decoder
|
||||||
@@ -48,11 +50,34 @@ feature -- Decoder
|
|||||||
-- The UTF8-encoded equivalent of the given string
|
-- The UTF8-encoded equivalent of the given string
|
||||||
do
|
do
|
||||||
Result := utf8_to_utf32 (v)
|
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
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
@@ -15,23 +15,24 @@ class
|
|||||||
inherit
|
inherit
|
||||||
URL_ENCODER
|
URL_ENCODER
|
||||||
redefine
|
redefine
|
||||||
default_create,
|
|
||||||
name,
|
name,
|
||||||
general_encoded_string,
|
general_encoded_string,
|
||||||
encoded_string, partial_encoded_string,
|
encoded_string, partial_encoded_string,
|
||||||
decoded_string
|
decoded_string
|
||||||
|
select
|
||||||
|
encoded_string,
|
||||||
|
decoded_string,
|
||||||
|
has_error
|
||||||
end
|
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
|
redefine
|
||||||
default_create
|
name
|
||||||
end
|
|
||||||
|
|
||||||
feature {NONE} -- Initialization
|
|
||||||
|
|
||||||
default_create
|
|
||||||
do
|
|
||||||
Precursor {UTF8_ENCODER_HELPER}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Access
|
feature -- Access
|
||||||
@@ -46,27 +47,22 @@ feature -- Encoder
|
|||||||
encoded_string (s: READABLE_STRING_32): STRING_8
|
encoded_string (s: READABLE_STRING_32): STRING_8
|
||||||
-- URL-encoded value of `s'.
|
-- URL-encoded value of `s'.
|
||||||
do
|
do
|
||||||
Result := utf32_to_utf8 (s)
|
Result := general_encoded_string (s)
|
||||||
Result := Precursor (Result)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
general_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
|
general_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
|
||||||
do
|
do
|
||||||
if attached {READABLE_STRING_32} s as s32 then
|
Result := utf8_general_encoded_string (s)
|
||||||
Result := utf32_to_utf8 (s32)
|
Result := Precursor {URL_ENCODER} (Result)
|
||||||
else
|
has_error := has_error or utf8_has_error
|
||||||
Result := s.as_string_8
|
|
||||||
end
|
|
||||||
Result := Precursor (Result)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
partial_encoded_string (s: READABLE_STRING_GENERAL; a_ignore: ARRAY [CHARACTER]): STRING_8
|
partial_encoded_string (s: READABLE_STRING_GENERAL; a_ignore: ARRAY [CHARACTER]): STRING_8
|
||||||
-- URL-encoded value of `s'.
|
-- URL-encoded value of `s'.
|
||||||
do
|
do
|
||||||
Result := Precursor (s, a_ignore)
|
Result := utf8_general_encoded_string (s)
|
||||||
if not has_error then
|
Result := Precursor {URL_ENCODER} (Result, a_ignore)
|
||||||
Result := utf32_to_utf8 (Result)
|
has_error := has_error or utf8_has_error
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
feature -- Decoder
|
feature -- Decoder
|
||||||
@@ -74,17 +70,15 @@ feature -- Decoder
|
|||||||
decoded_string (v: READABLE_STRING_8): STRING_32
|
decoded_string (v: READABLE_STRING_8): STRING_32
|
||||||
-- The URL-encoded equivalent of the given string
|
-- The URL-encoded equivalent of the given string
|
||||||
do
|
do
|
||||||
Result := Precursor (v)
|
Result := Precursor {URL_ENCODER} (v)
|
||||||
if not has_error then
|
if not has_error then
|
||||||
if is_valid_utf8 (Result) then
|
Result := utf8_decoded_string (Result)
|
||||||
Result := utf8_to_utf32 (Result)
|
has_error := utf8_has_error
|
||||||
has_error := not last_conversion_successful
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
note
|
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)"
|
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||||
source: "[
|
source: "[
|
||||||
Eiffel Software
|
Eiffel Software
|
||||||
|
|||||||
BIN
tools/bin/ecf_updater.exe
Normal file
BIN
tools/bin/ecf_updater.exe
Normal file
Binary file not shown.
Reference in New Issue
Block a user