Merge branch 'master' into handler

pull from upstream
This commit is contained in:
Colin Adams
2013-07-08 10:17:44 +01:00
286 changed files with 2211 additions and 19154 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="http_authorization" uuid="321674DB-CE7C-417C-ADE8-64CFA376CD3E" library_target="http_authorization">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="http_authorization" uuid="321674DB-CE7C-417C-ADE8-64CFA376CD3E" library_target="http_authorization">
<target name="http_authorization">
<root all_classes="true"/>
<file_rule>
@@ -9,8 +9,8 @@
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</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="encoder" location="..\..\..\text\encoder\encoder-safe.ecf"/>
<cluster name="src" location="./src" recursive="true"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="ewf_support" uuid="BDBAA858-2658-4169-A44A-0BB61E3B40E7" library_target="ewf_support">
<target name="ewf_support">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="false">
<cluster name="before_72" location="$|before_72\">
<condition>
<version type="compiler" max="7.1.9.9999"/>
</condition>
</cluster>
<cluster name="greater_or_72" location="$|greater_or_72\">
<condition>
<version type="compiler" min="7.2.0.0"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="ewf_support" uuid="BDBAA858-2658-4169-A44A-0BB61E3B40E7" library_target="ewf_support">
<target name="ewf_support">
<root all_classes="true"/>
<file_rule>
<exclude>/.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" void_safety="none" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY/library/base/base.ecf"/>
<cluster name="src" location=".\src\" recursive="false">
<cluster name="before_72" location="$|before_72\">
<condition>
<version type="compiler" max="7.1.9.9999"/>
</condition>
</cluster>
<cluster name="greater_or_72" location="$|greater_or_72\">
<condition>
<version type="compiler" min="7.2.0.0"/>
</condition>
</cluster>
</cluster>
</target>
</system>

View File

@@ -1,49 +0,0 @@
note
description: "Shared instance of execution environment."
legal: "See notice at end of class."
status: "See notice at end of class."
date: "$Date$"
revision: "$Revision$"
class
SHARED_EXECUTION_ENVIRONMENT
feature {NONE}
Execution_environment: EXECUTION_ENVIRONMENT
once
create Result
end
note
copyright: "Copyright (c) 2012, Eiffel Software"
license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
licensing_options: "http://www.eiffel.com/licensing"
copying: "[
This file is part of Eiffel Software's Eiffel Development Environment.
Eiffel Software's Eiffel Development Environment is free
software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published
by the Free Software Foundation, version 2 of the License
(available at the URL listed under "license" above).
Eiffel Software's Eiffel Development Environment is
distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public
License along with Eiffel Software's Eiffel Development
Environment; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
]"
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

View File

@@ -1,36 +0,0 @@
note
description: "[
The WSF_SUPPORT class is meant to handle incompatibilities between version of libraries
And still allow to benefit from most recent improvements.
Unicode is an example
]"
date: "$Date$"
revision: "$Revision$"
class
WSF_SUPPORT
inherit
ANY
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
feature -- Access: environment
starting_environment: HASH_TABLE [READABLE_STRING_GENERAL, READABLE_STRING_GENERAL]
do
Result := execution_environment.starting_environment_variables
end
environment_item (a_name: READABLE_STRING_GENERAL): detachable STRING_32
do
if attached execution_environment.get (a_name.to_string_8) as v then
Result := v.to_string_32
end
end
end

View File

@@ -1,34 +0,0 @@
note
description: "[
The WSF_SUPPORT class is meant to handle incompatibilities between version of libraries
And still allow to benefit from most recent improvements.
Unicode is an example
]"
date: "$Date$"
revision: "$Revision$"
class
WSF_SUPPORT
inherit
ANY
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
feature -- Access: environment
starting_environment: HASH_TABLE [READABLE_STRING_GENERAL, READABLE_STRING_GENERAL]
do
Result := execution_environment.starting_environment
end
environment_item (a_name: READABLE_STRING_GENERAL): detachable STRING_32
do
Result := execution_environment.item (a_name)
end
end

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_cgi" uuid="3BCBC1C5-9D99-45BB-B15D-B03D2C069CED" library_target="connector_cgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="connector_cgi" uuid="3BCBC1C5-9D99-45BB-B15D-B03D2C069CED" library_target="connector_cgi">
<target name="connector_cgi">
<root all_classes="true"/>
<file_rule>
@@ -7,11 +7,11 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="http" location="../../../../network/protocol/http/http-safe.ecf"/>
<library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -52,19 +52,23 @@ feature -- Execution
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
end
if res.message_writable then
res.put_string ("<pre>" + l_trace + "</pre>")
res.put_string ("<pre>")
res.put_string (l_trace)
res.put_string ("</pre>")
end
res.push
end
end
end
rescue
rescued := True
retry
if not rescued then
rescued := True
retry
end
end
note
copyright: "2011-2012, Eiffel Software and others"
copyright: "2011-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_libfcgi" uuid="59C57E56-3EE6-4EF7-873F-7ED084B0EB22" library_target="connector_libfcgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="connector_libfcgi" uuid="59C57E56-3EE6-4EF7-873F-7ED084B0EB22" library_target="connector_libfcgi">
<target name="connector_libfcgi">
<root all_classes="true"/>
<file_rule>
@@ -7,12 +7,12 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf"/>
<library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="libfcgi" location="..\..\..\libfcgi\libfcgi-safe.ecf"/>
<library name="http" location="../../../../network/protocol/http/http-safe.ecf"/>
<cluster name="src" location=".\" recursive="true"/>
</target>
</system>

View File

@@ -55,7 +55,7 @@ feature -- Server
feature -- Execution
process_fcgi_request (vars: HASH_TABLE [STRING, STRING]; a_input: like input; a_output: like output)
process_fcgi_request (vars: STRING_TABLE [READABLE_STRING_8]; a_input: like input; a_output: like output)
local
req: WGI_REQUEST_FROM_TABLE
res: detachable WGI_RESPONSE_STREAM
@@ -73,15 +73,19 @@ feature -- Execution
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
end
if res.message_writable then
res.put_string ("<pre>" + l_trace + "</pre>")
res.put_string ("<pre>")
res.put_string (l_trace)
res.put_string ("</pre>")
end
res.push
end
end
end
rescue
rescued := True
retry
if not rescued then
rescued := True
retry
end
end
feature -- Input/Output
@@ -100,7 +104,7 @@ invariant
fcgi_attached: fcgi /= Void
note
copyright: "2011-2011, Eiffel Software and others"
copyright: "2011-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -127,20 +127,28 @@ feature -- Server
server.setup (l_http_handler)
end
process_request (env: HASH_TABLE [STRING, STRING]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET)
process_request (env: STRING_TABLE [READABLE_STRING_8]; a_headers_text: STRING; a_socket: TCP_STREAM_SOCKET)
local
req: WGI_REQUEST_FROM_TABLE
res: detachable WGI_NINO_RESPONSE_STREAM
retried: BOOLEAN
do
create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current)
create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out))
req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text)
service.execute (req, res)
res.push
if not retried then
create req.make (env, create {WGI_NINO_INPUT_STREAM}.make (a_socket), Current)
create res.make (create {WGI_NINO_OUTPUT_STREAM}.make (a_socket), create {WGI_NINO_ERROR_STREAM}.make_stderr (a_socket.descriptor.out))
req.set_meta_string_variable ("RAW_HEADER_DATA", a_headers_text)
service.execute (req, res)
res.push
end
rescue
if not retried then
retried := True
retry
end
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -61,24 +61,24 @@ feature -- Request processing
process_request (a_handler: HTTP_CONNECTION_HANDLER; a_socket: TCP_STREAM_SOCKET)
-- Process request ...
local
env: HASH_TABLE [STRING, STRING]
env: STRING_TABLE [READABLE_STRING_8]
p: INTEGER
l_request_uri, l_script_name, l_query_string, l_path_info: STRING
l_server_name, l_server_port: detachable STRING
a_headers_map: HASH_TABLE [STRING, STRING]
l_headers_map: HASH_TABLE [STRING, STRING]
vn: STRING
e: EXECUTION_ENVIRONMENT
do
l_request_uri := a_handler.uri
a_headers_map := a_handler.request_header_map
l_headers_map := a_handler.request_header_map
create e
if attached e.starting_environment_variables as vars then
create env.make (vars.count)
create env.make_equal (vars.count)
across
vars as c
loop
env.force (c.item.to_string_8, c.key.to_string_8)
env.force (c.item.to_string_8, c.key)
end
else
create env.make (0)
@@ -86,11 +86,11 @@ feature -- Request processing
--| for Any Abc-Def-Ghi add (or replace) the HTTP_ABC_DEF_GHI variable to `env'
from
a_headers_map.start
l_headers_map.start
until
a_headers_map.after
l_headers_map.after
loop
create vn.make_from_string (a_headers_map.key_for_iteration.as_upper)
create vn.make_from_string (l_headers_map.key_for_iteration.as_upper)
vn.replace_substring_all ("-", "_")
if
vn.starts_with ("CONTENT_") and then
@@ -100,8 +100,8 @@ feature -- Request processing
else
vn.prepend ("HTTP_")
end
add_environment_variable (a_headers_map.item_for_iteration, vn, env)
a_headers_map.forth
add_environment_variable (l_headers_map.item_for_iteration, vn, env)
l_headers_map.forth
end
--| Specific cases
@@ -114,7 +114,7 @@ feature -- Request processing
l_script_name := l_request_uri.string
l_query_string := ""
end
if attached a_headers_map.item ("Host") as l_host then
if attached l_headers_map.item ("Host") as l_host then
check has_host: env.has ("HTTP_HOST") end
-- set_environment_variable (l_host, "HTTP_HOST", env)
p := l_host.index_of (':', 1)
@@ -129,7 +129,7 @@ feature -- Request processing
check host_available: False end
end
if attached a_headers_map.item ("Authorization") as l_authorization then
if attached l_headers_map.item ("Authorization") as l_authorization then
check has_authorization: env.has ("HTTP_AUTHORIZATION") end
-- set_environment_variable (l_authorization, "HTTP_AUTHORIZATION", env)
p := l_authorization.index_of (' ', 1)
@@ -174,7 +174,7 @@ feature -- Request processing
callback.process_request (env, a_handler.request_header, a_socket)
end
add_environment_variable (a_value: detachable STRING; a_var_name: STRING; env: HASH_TABLE [STRING, STRING])
add_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8])
-- Add variable `a_var_name => a_value' to `env'
do
if a_value /= Void then
@@ -188,7 +188,7 @@ feature -- Request processing
end
end
set_environment_variable (a_value: detachable STRING; a_var_name: STRING; env: HASH_TABLE [STRING, STRING])
set_environment_variable (a_value: detachable STRING; a_var_name: READABLE_STRING_GENERAL; env: STRING_TABLE [READABLE_STRING_8])
-- Add variable `a_var_name => a_value' to `env'
do
if a_value /= Void then
@@ -197,7 +197,7 @@ feature -- Request processing
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="connector_null" uuid="D55DC7A7-AAFA-43C6-B432-A192FF64141E" library_target="connector_null">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="connector_null" uuid="D55DC7A7-AAFA-43C6-B432-A192FF64141E" library_target="connector_null">
<target name="connector_null">
<root all_classes="true"/>
<file_rule>
@@ -7,11 +7,11 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all">
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi-safe.ecf" readonly="false"/>
<library name="http" location="../../../../network/protocol/http/http-safe.ecf"/>
<library name="http" location="..\..\..\..\network\protocol\http\http-safe.ecf"/>
<cluster name="src" location=".\src\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="ewsgi" uuid="D924DBE1-1231-434A-80EF-234BA09D1E30" library_target="ewsgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="ewsgi" uuid="D924DBE1-1231-434A-80EF-234BA09D1E30" library_target="ewsgi">
<target name="ewsgi">
<root all_classes="true"/>
<file_rule>
@@ -10,15 +10,15 @@
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="error" location="../../utility/general/error/error-safe.ecf"/>
<library name="http" location="../../network/protocol/http/http-safe.ecf"/>
<library name="encoder" location="..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="..\..\utility\general\error\error-safe.ecf"/>
<library name="http" location="..\..\network\protocol\http\http-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<cluster name="interface" location="src\" recursive="true"/>
<cluster name="specification_request" location="specification\request" recursive="true"/>
<cluster name="specification_response" location="specification\response" recursive="true"/>
<cluster name="specification_connector" location="specification\connector" recursive="true"/>
<cluster name="specification_service" location="specification\service" recursive="true"/>
<cluster name="specification_stream" location="specification\stream" recursive="true"/>
<cluster name="specification_connector" location="specification\connector\" recursive="true"/>
<cluster name="specification_request" location="specification\request\" recursive="true"/>
<cluster name="specification_response" location="specification\response\" recursive="true"/>
<cluster name="specification_service" location="specification\service\" recursive="true"/>
<cluster name="specification_stream" location="specification\stream\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="ewsgi_spec" uuid="AA193B9F-02FD-47B9-B60D-C42B9AB35E1C" library_target="ewsgi_spec">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="ewsgi_spec" uuid="AA193B9F-02FD-47B9-B60D-C42B9AB35E1C" library_target="ewsgi_spec">
<target name="ewsgi_spec">
<root all_classes="true"/>
<file_rule>

View File

@@ -88,14 +88,14 @@ feature -- Access: Input
feature -- Access: CGI meta variables
meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
meta_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- Environment variable related to `a_name'
require
a_name_valid: a_name /= Void and then not a_name.is_empty
deferred
end
meta_string_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
meta_string_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- Environment variable related to `a_name'
require
a_name_valid: a_name /= Void and then not a_name.is_empty
@@ -105,7 +105,7 @@ feature -- Access: CGI meta variables
end
end
meta_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
meta_variables: STRING_TABLE [READABLE_STRING_8]
-- These variables are specific to requests made with HTTP.
-- Interpretation of these variables may depend on the value of
-- SERVER_PROTOCOL.
@@ -665,7 +665,7 @@ invariant
path_info_identical: path_info ~ meta_string_variable ({WGI_META_NAMES}.path_info)
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -25,9 +25,9 @@ feature {NONE} -- Initialization
make_with_response_and_output (res: WGI_RESPONSE; a_out: FILE; a_err: FILE)
do
make_with_response (res)
output := a_out
error := a_err
make_with_response (res)
end
output: FILE
@@ -104,7 +104,7 @@ feature -- Error reporting
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -123,6 +123,52 @@ feature -- Input
character_read: not end_of_input implies last_appended_count > 0
end
append_to_file (a_file: FILE; nb: INTEGER)
-- Append at most `nb' characters read from input stream
-- to `a_file'
-- Set `last_appended_count' to the number of characters actually read.
-- (Note that even if at least `nb' characters are available
-- in the input stream, there is no guarantee that they
-- will all be read.)
require
is_open_read: is_open_read
not_end_of_input: not end_of_input
a_file_attached: a_file /= Void
a_file_is_open_write: a_file.is_open_write
nb_large_enough: nb > 0
local
s: like last_string
n: INTEGER
l_remaining: INTEGER
do
from
n := nb.min (2_048)
l_remaining := nb - n
until
l_remaining = 0 or n = 0
loop
read_string (n)
s := last_string
a_file.put_string (s)
if end_of_input or s.count < n then
n := s.count
-- no more data
l_remaining := l_remaining - n
n := 0
else
n := s.count
l_remaining := l_remaining - n
end
end
last_appended_count := nb - l_remaining
-- Clean `last_string'
last_string.wipe_out
ensure
nb_char_read_large_enough: last_appended_count >= 0
nb_char_read_small_enough: last_appended_count <= nb
character_read: not end_of_input implies last_appended_count > 0
end
feature -- Access
last_string: STRING_8
@@ -166,7 +212,7 @@ feature -- Status report
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -61,16 +61,16 @@ feature -- EWSGI access
feature -- Access: CGI meta parameters
meta_variables: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
meta_variables: STRING_TABLE [READABLE_STRING_8]
-- CGI Environment parameters
meta_variable (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
meta_variable (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
-- CGI meta variable related to `a_name'
do
Result := meta_variables.item (a_name)
end
meta_string_variable_or_default (a_name: READABLE_STRING_8; a_default: READABLE_STRING_8; use_default_when_empty: BOOLEAN): READABLE_STRING_8
meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_8; use_default_when_empty: BOOLEAN): READABLE_STRING_8
-- Value for meta parameter `a_name'
-- If not found, return `a_default'
require
@@ -86,14 +86,14 @@ feature -- Access: CGI meta parameters
end
end
set_meta_string_variable (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8)
set_meta_string_variable (a_name: READABLE_STRING_GENERAL; a_value: READABLE_STRING_8)
do
meta_variables.force (a_value, a_name)
ensure
param_set: attached meta_variable (a_name) as val and then val ~ a_value
end
unset_meta_variable (a_name: READABLE_STRING_8)
unset_meta_variable (a_name: READABLE_STRING_GENERAL)
do
meta_variables.remove (a_name)
ensure
@@ -304,7 +304,7 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
-- Fill with variable from `a_vars'
local
s: like meta_string_variable
table: HASH_TABLE [READABLE_STRING_8, READABLE_STRING_8]
table: STRING_TABLE [READABLE_STRING_8]
l_query_string: like query_string
l_request_uri: detachable STRING_32
l_empty_string: like empty_string
@@ -312,15 +312,14 @@ feature {NONE} -- Element change: CGI meta parameter related to PATH_INFO
create {STRING_8} l_empty_string.make_empty
empty_string := l_empty_string
create table.make (a_vars.count)
table.compare_objects
create table.make_equal (a_vars.count)
meta_variables := table
from
a_vars.start
until
a_vars.after
loop
table.force (a_vars.item_for_iteration.to_string_8, a_vars.key_for_iteration.to_string_8)
table.force (a_vars.item_for_iteration.to_string_8, a_vars.key_for_iteration)
a_vars.forth
end
@@ -482,7 +481,7 @@ invariant
empty_string_unchanged: empty_string.is_empty
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -19,21 +19,21 @@ feature {NONE} -- Initialization
feature -- Access
updated_environ_variables: HASH_TABLE [STRING, STRING]
updated_environ_variables: STRING_TABLE [READABLE_STRING_8]
local
i: INTEGER
p, v, null: POINTER
do
p := fcgi_environ
create Result.make (50)
create Result.make_equal (50)
if p /= null then
from
i := 0
v := fcgi_i_th_environ (i,p)
v := fcgi_i_th_environ (i, p)
until
v = null
loop
if attached separated_variables (create {STRING}.make_from_c (v)) as t then
if attached separated_variables (create {STRING_8}.make_from_c (v)) as t then
Result.force (t.value, t.key)
end
i := i + 1
@@ -196,7 +196,7 @@ feature {NONE} -- Implementation: Environment
"return ((char **)$p)[$i];"
end
separated_variables (a_var: STRING): detachable TUPLE [value: STRING; key: STRING]
separated_variables (a_var: READABLE_STRING_8): detachable TUPLE [value: READABLE_STRING_8; key: READABLE_STRING_8]
-- Given an environment variable `a_var' in form of "key=value",
-- return separated key and value.
-- Return Void if `a_var' is in incorrect format.
@@ -224,7 +224,7 @@ feature {NONE} -- Implementation: Environment
end
note
copyright: "Copyright (c) 1984-2011, Eiffel Software and others"
copyright: "Copyright (c) 1984-2013, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-6-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-6-0 http://www.eiffel.com/developers/xml/configuration-1-6-0.xsd" name="libfcgi" uuid="3F4BCF74-3503-4533-9D74-5A65EC4CA3C4" library_target="libfcgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="libfcgi" uuid="3F4BCF74-3503-4533-9D74-5A65EC4CA3C4" library_target="libfcgi">
<target name="libfcgi">
<root all_classes="true"/>
<file_rule>
<exclude>/\.svn$</exclude>
<exclude>/\.git$</exclude>
<exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" >
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="transitional">
</option>
<external_include location="$ECF_CONFIG_PATH/spec/include/libfcgi">
<condition>
@@ -31,8 +30,7 @@
</condition>
</external_library>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<cluster name="interface" location="interface" recursive="true"/>
<cluster name="implementation" location="implementation" recursive="true">
<cluster name="implementation" location="implementation\" recursive="true">
<file_rule>
<exclude>/linux$</exclude>
<exclude>/fake$</exclude>
@@ -41,12 +39,13 @@
</condition>
</file_rule>
<file_rule>
<exclude>/windows$</exclude>
<exclude>/fake$</exclude>
<exclude>/windows$</exclude>
<condition>
<platform excluded_value="windows"/>
</condition>
</file_rule>
</cluster>
<cluster name="interface" location="interface\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_cgi" uuid="1B416A7F-D49B-43FC-8308-F14AA9531AF8" library_target="wsf_cgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_cgi" uuid="1B416A7F-D49B-43FC-8308-F14AA9531AF8" library_target="wsf_cgi">
<target name="wsf_cgi">
<root all_classes="true"/>
<file_rule>
@@ -10,13 +10,13 @@
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="ewsgi" location="../../ewsgi/ewsgi-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="connector_cgi" location="../../ewsgi/connectors/cgi/cgi-safe.ecf"/>
<library name="error" location="../../../utility/general/error/error-safe.ecf"/>
<library name="http" location="../../../network/protocol/http/http-safe.ecf"/>
<library name="connector_cgi" location="..\..\ewsgi\connectors\cgi\cgi-safe.ecf"/>
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<cluster name="wsf_cgi" location="./cgi" recursive="true"/>
<library name="error" location="..\..\..\utility\general\error\error-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<cluster name="wsf_cgi" location=".\cgi\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_libfcgi" uuid="00B169F1-2BE2-4986-8B93-825FEB944FFD" library_target="wsf_libfcgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_libfcgi" uuid="00B169F1-2BE2-4986-8B93-825FEB944FFD" library_target="wsf_libfcgi">
<target name="wsf_libfcgi">
<root all_classes="true"/>
<file_rule>
@@ -10,13 +10,13 @@
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="ewsgi" location="../../ewsgi/ewsgi-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="connector_libfcgi" location="../../ewsgi/connectors/libfcgi/libfcgi-safe.ecf"/>
<library name="error" location="../../../utility/general/error/error-safe.ecf"/>
<library name="http" location="../../../network/protocol/http/http-safe.ecf"/>
<library name="connector_libfcgi" location="..\..\ewsgi\connectors\libfcgi\libfcgi-safe.ecf"/>
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<cluster name="wsf_libfcgi" location="./libfcgi" recursive="true"/>
<library name="error" location="..\..\..\utility\general\error\error-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<cluster name="wsf_libfcgi" location=".\libfcgi\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_nino" uuid="BACF0220-900B-4409-8CB2-30A09836A650" library_target="wsf_nino">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="wsf_nino" uuid="BACF0220-900B-4409-8CB2-30A09836A650" library_target="wsf_nino">
<target name="wsf_nino">
<root all_classes="true"/>
<file_rule>
@@ -10,17 +10,16 @@
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="ewsgi" location="../../ewsgi/ewsgi-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="connector_nino" location="../../ewsgi/connectors/nino/nino-safe.ecf"/>
<library name="connector_nino" location="..\..\ewsgi\connectors\nino\nino-safe.ecf"/>
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<library name="error" location="..\..\..\utility\general\error\error-safe.ecf"/>
<library name="ewsgi" location="..\..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\..\network\protocol\http\http-safe.ecf"/>
<library name="nino" location="..\..\..\..\contrib\library\network\server\nino\nino-safe.ecf" readonly="false">
<renaming old_name="HTTP_CONSTANTS" new_name="NINO_HTTP_CONSTANTS"/>
</library>
<library name="error" location="../../../utility/general/error/error-safe.ecf"/>
<library name="http" location="../../../network/protocol/http/http-safe.ecf"/>
<library name="encoder" location="..\..\..\text\encoder\encoder-safe.ecf" readonly="false"/>
<cluster name="wsf_nino" location="./nino" recursive="true"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<cluster name="wsf_nino" location=".\nino\" recursive="true"/>
</target>
</system>

View File

@@ -24,6 +24,11 @@ inherit
initialize
end
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
create
make,
make_and_launch,
@@ -37,15 +42,19 @@ feature {NONE} -- Initialization
l_env: EXECUTION_ENVIRONMENT
do
Precursor
create l_env
l_env := execution_environment
if attached l_env.get (Openshift_ip) as l_ip then
server_name := l_ip.to_string_8
if attached l_env.item (Openshift_ip) as l_ip then
if l_ip.is_valid_as_string_8 then
server_name := l_ip.to_string_8
else
die ("could not parse " + Openshift_ip)
end
else
die (Openshift_ip + " is not defined")
end
if attached l_env.get (Openshift_port) as l_port then
if attached l_env.item (Openshift_port) as l_port then
if l_port.is_integer then
port_number := l_port.to_integer
else
@@ -77,7 +86,7 @@ feature {NONE} -- Implementation
;note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="default_cgi" uuid="A9137009-B5BA-4C58-BCD3-7753909918B5" library_target="default_cgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="default_cgi" uuid="A9137009-B5BA-4C58-BCD3-7753909918B5" library_target="default_cgi">
<target name="default_cgi">
<root all_classes="true"/>
<file_rule>
@@ -7,10 +7,11 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional"/>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="wsf_cgi" location="../connector/cgi-safe.ecf"/>
<cluster name="default_cgi" location="./cgi" recursive="true"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<library name="wsf_cgi" location="..\connector\cgi-safe.ecf"/>
<cluster name="default_cgi" location=".\cgi\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="default_libfcgi" uuid="B853CC3A-D173-4DA4-9832-6D0148C8F01F" library_target="default_libfcgi">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="default_libfcgi" uuid="B853CC3A-D173-4DA4-9832-6D0148C8F01F" library_target="default_libfcgi">
<target name="default_libfcgi">
<root all_classes="true"/>
<file_rule>
@@ -7,10 +7,11 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional"/>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="wsf_libfcgi" location="../connector/libfcgi-safe.ecf"/>
<cluster name="default_libfcgi" location="./libfcgi" recursive="true"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<library name="wsf_libfcgi" location="..\connector\libfcgi-safe.ecf"/>
<cluster name="default_libfcgi" location=".\libfcgi\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="default_nino" uuid="ACBEDC97-956C-45F5-97E3-65A6D9987625" library_target="default_nino">
<target name="default_nino">
<root all_classes="true"/>
<file_rule>
@@ -7,10 +7,11 @@
<exclude>/\.git$</exclude>
<exclude>/\.svn$</exclude>
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional"/>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="provisional">
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="wsf" location="../wsf-safe.ecf"/>
<library name="wsf_nino" location="../connector/nino-safe.ecf"/>
<cluster name="default_nino" location="./nino" recursive="true"/>
<library name="wsf" location="..\wsf-safe.ecf"/>
<library name="wsf_nino" location="..\connector\nino-safe.ecf"/>
<cluster name="default_nino" location=".\nino\" recursive="true"/>
</target>
</system>

View File

@@ -137,7 +137,7 @@ feature {WSF_RESPONSE} -- Output
debug
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>REQUEST_URI=" + request.request_uri + "</li>")
l_description.append ("<li>SCRIPT_NAME=" + request.script_name + "</li>")

View File

@@ -68,10 +68,6 @@ feature -- Basic operations
end
end
feature -- Constants
Date_time_format: STRING = "[0]dd/[0]mm/yyyy [0]hh:[0]mi:[0]ss"
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)"

View File

@@ -20,7 +20,7 @@ feature -- Execution
a_start_path_attached: a_start_path /= Void
req_attached: req /= Void
res_attached: res /= Void
path_start_with_a_start_path: req.path_info.starts_with (a_start_path)
path_start_with_a_start_path: req.percent_encoded_path_info.starts_with (a_start_path)
deferred
end
@@ -33,7 +33,7 @@ feature {WSF_ROUTER} -- Mapping
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -83,7 +83,7 @@ feature {NONE} -- Execution
a_start_path_attached: a_start_path /= Void
req_attached: req /= Void
res_attached: res /= Void
path_start_with_a_start_path: req.path_info.starts_with (a_start_path)
path_start_with_a_start_path: req.percent_encoded_path_info.starts_with (a_start_path)
deferred
end

View File

@@ -61,7 +61,7 @@ feature -- Status
-- <Precursor>
local
tpl: URI_TEMPLATE
p: READABLE_STRING_32
p: READABLE_STRING_8
do
p := path_from_request (req)
tpl := based_uri_template (template, a_router)
@@ -72,7 +72,7 @@ feature -- Status
-- <Precursor>
local
tpl: URI_TEMPLATE
p: READABLE_STRING_32
p: READABLE_STRING_8
new_src: detachable WSF_REQUEST_PATH_PARAMETERS_PROVIDER
do
p := path_from_request (req)

View File

@@ -15,31 +15,53 @@ inherit
WSF_SELF_DOCUMENTED_HANDLER
SHARED_HTML_ENCODER
SHARED_WSF_PERCENT_ENCODER
rename
percent_encoder as url_encoder
export
{NONE} all
end
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
create
make_with_path,
make_hidden_with_path,
make,
make_hidden
feature {NONE} -- Initialization
make (d: like document_root)
require
valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
local
e: EXECUTION_ENVIRONMENT
make_with_path (d: like document_root)
do
if d.is_empty then
create e
document_root := e.current_working_directory
document_root := execution_environment.current_working_path
else
document_root := d
end
ensure
not document_root.is_empty and then not document_root.ends_with (operating_environment.directory_separator.out)
not document_root.is_empty
end
make_hidden (d: like document_root)
require
valid_d: (d /= Void and then not d.is_empty) implies not d.ends_with (operating_environment.directory_separator.out)
make_hidden_with_path (d: like document_root)
do
make_with_path (d)
is_hidden := True
ensure
hidden: is_hidden
end
make (d: READABLE_STRING_GENERAL)
do
make_with_path (create {PATH}.make_from_string (d))
end
make_hidden (d: READABLE_STRING_GENERAL)
do
make (d)
is_hidden := True
@@ -60,16 +82,21 @@ feature -- Documentation
Result.add_description ("File service")
end
feature -- Access
feature -- Access
document_root: PATH
document_root: STRING
max_age: INTEGER
index_disabled: BOOLEAN
-- Index disabled?
index_ignores_function: detachable FUNCTION [ANY, TUPLE [PATH], BOOLEAN]
-- Function to evaluate if a path is ignored or not during autoindex.
-- If `index_ignores' is Void and `index_ignores_function' is Void, use default ignore rules.
directory_index: detachable ARRAY [READABLE_STRING_8]
-- File serve if a directory index is requested
-- File serve if a directory index is requested.
not_found_handler: detachable PROCEDURE [ANY, TUPLE [uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE]]
@@ -114,14 +141,52 @@ feature -- Element change
access_denied_handler := h
end
set_default_index_ignores
-- Use default auto index ignores behavior.
do
index_ignores_function := Void
end
set_index_ignores_function (fct: attached like index_ignores_function)
-- Use `fct' to compute auto index ignores behavior.
do
index_ignores_function := fct
end
feature -- Status report
ignoring_index_entry (p: PATH): BOOLEAN
-- Ignoring path `p' for auto index?
local
e: detachable PATH
n: READABLE_STRING_32
do
if attached index_ignores_function as fct then
Result := fct.item ([p])
else
-- default
e := p.entry
if e = Void then
e := p
end
if e.is_parent_symbol then
else
n := e.name
Result := n.starts_with ({STRING_32} ".")
or n.ends_with ({STRING_32} "~")
or n.ends_with ({STRING_32} ".swp")
end
end
end
feature -- Execution
execute (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
local
p: STRING
p: STRING_32
do
p := req.path_info
if p.starts_with (a_start_path) then
create p.make_from_string (req.path_info)
if p.starts_with_general (a_start_path) then
p.remove_head (a_start_path.count)
else
check starts_with_base: False end
@@ -131,16 +196,16 @@ feature -- Execution
execute_starts_with (a_start_path: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
do
execute (a_start_path,req, res)
execute (a_start_path, req, res)
end
process_uri (uri: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
process_uri (uri: READABLE_STRING_32; req: WSF_REQUEST; res: WSF_RESPONSE)
local
f: RAW_FILE
fn: READABLE_STRING_8
fn: like resource_filename
do
fn := resource_filename (uri)
create f.make (fn)
create f.make_with_path (fn)
if f.exists then
if f.is_readable then
if f.is_directory then
@@ -160,14 +225,20 @@ feature -- Execution
end
end
process_index (a_uri: READABLE_STRING_8; dn: READABLE_STRING_8; req: WSF_REQUEST; res: WSF_RESPONSE)
process_index (a_uri: READABLE_STRING_8; dn: PATH; req: WSF_REQUEST; res: WSF_RESPONSE)
local
h: HTTP_HEADER
uri, s: STRING_8
d: DIRECTORY
l_files: LIST [STRING_8]
l_files: LIST [PATH]
p: PATH
n: READABLE_STRING_32
httpdate: HTTP_DATE
pf: RAW_FILE
l_is_dir: BOOLEAN
do
create d.make_open_read (dn)
create d.make_with_path (dn)
d.open_read
if attached directory_index_file (d) as f then
process_file (f, req, res)
else
@@ -178,25 +249,73 @@ feature -- Execution
s := "[
<html>
<head>
<title>Index for folder: $URI</title>
<title>Index of $URI</title>
<style>
td { padding-left: 10px;}
</style>
</head>
<body>
<h1>Index for $URI</h1>
<ul>
<h1>Index of $URI</h1>
<table>
<tr><th/><th>Name</th><th>Last modified</th><th>Size</th></tr>
<tr><th colspan="4"><hr></th></tr>
]"
s.replace_substring_all ("$URI", uri)
from
l_files := d.linear_representation
l_files := d.entries
l_files.start
until
l_files.after
loop
s.append ("<li><a href=%"" + uri + l_files.item_for_iteration + "%">" + l_files.item_for_iteration + "</a></li>%N")
p := l_files.item
if ignoring_index_entry (p) then
else
n := p.name
create pf.make_with_path (p)
if pf.is_directory then
l_is_dir := True
else
l_is_dir := False
end
s.append ("<tr><td>")
if l_is_dir then
s.append ("[dir]")
else
s.append ("&nbsp;")
end
s.append ("</td>")
s.append ("<td><a href=%"" + uri)
url_encoder.append_percent_encoded_string_to (n, s)
s.append ("%">")
if p.is_parent_symbol then
s.append ("[Parent Directory] ..")
else
s.append (html_encoder.encoded_string (n))
end
if l_is_dir then
s.append ("/")
end
s.append ("</td>")
s.append ("<td>")
create httpdate.make_from_date_time (file_date (pf))
httpdate.append_to_rfc1123_string (s)
s.append ("</td>")
s.append ("<td>")
if not l_is_dir then
s.append_integer (file_size (pf))
end
s.append ("</td>")
s.append ("</tr>")
end
l_files.forth
end
s.append ("[
</ul>
<tr><th colspan="4"><hr></th></tr>
</table>
</body>
</html>
]"
@@ -217,12 +336,12 @@ feature -- Execution
process_file (f: FILE; req: WSF_REQUEST; res: WSF_RESPONSE)
local
ext: READABLE_STRING_8
ext: READABLE_STRING_32
ct: detachable READABLE_STRING_8
fres: WSF_FILE_RESPONSE
dt: DATE_TIME
do
ext := extension (f.name)
ext := extension (f.path.name)
ct := extension_mime_mapping.mime_type (ext)
if ct = Void then
ct := {HTTP_MIME_TYPES}.application_force_download
@@ -235,7 +354,7 @@ feature -- Execution
then
process_not_modified (f_date, req, res)
else
create fres.make_with_content_type (ct, f.name)
create fres.make_with_content_type (ct, f.path.name)
fres.set_status_code ({HTTP_STATUS_CODE}.ok)
-- cache control
@@ -341,7 +460,7 @@ feature {NONE} -- Implementation
directory_index_file (d: DIRECTORY): detachable FILE
local
f: detachable RAW_FILE
fn: FILE_NAME
fn: PATH
do
if attached directory_index as default_index then
across
@@ -350,12 +469,11 @@ feature {NONE} -- Implementation
Result /= Void
loop
if d.has_entry (c.item) then
create fn.make_from_string (d.name)
fn.set_file_name (c.item)
fn := d.path.extended (c.item)
if f = Void then
create f.make (fn.string)
create f.make_with_path (fn)
else
f.make (fn.string)
f.make_with_path (fn)
end
if f.exists and then f.is_readable then
Result := f
@@ -365,28 +483,34 @@ feature {NONE} -- Implementation
end
end
resource_filename (uri: READABLE_STRING_8): READABLE_STRING_8
do
Result := real_filename (document_root + operating_environment.directory_separator.out + real_filename (uri))
end
dirname (uri: READABLE_STRING_8): READABLE_STRING_8
resource_filename (uri: READABLE_STRING_32): PATH
local
p: INTEGER
s: like uri_path_to_filename
do
p := uri.last_index_of ('/', uri.count)
if p > 0 then
Result := uri.substring (1, p - 1)
else
create {STRING_8} Result.make_empty
Result := document_root
s := uri_path_to_filename (uri)
if not s.is_empty then
Result := Result.extended (s)
end
end
filename (uri: READABLE_STRING_8): READABLE_STRING_8
dirname (uri: READABLE_STRING_32): READABLE_STRING_32
local
p: INTEGER
do
p := uri.last_index_of ('/', uri.count)
p := uri.last_index_of ({CHARACTER_32} '/', uri.count)
if p > 0 then
Result := uri.substring (1, p - 1)
else
create {STRING_32} Result.make_empty
end
end
filename (uri: READABLE_STRING_32): READABLE_STRING_32
local
p: INTEGER
do
p := uri.last_index_of ({CHARACTER_32} '/', uri.count)
if p > 0 then
Result := uri.substring (p + 1, uri.count)
else
@@ -394,58 +518,52 @@ feature {NONE} -- Implementation
end
end
extension (uri: READABLE_STRING_8): READABLE_STRING_8
extension (uri: READABLE_STRING_32): READABLE_STRING_32
local
p: INTEGER
do
p := uri.last_index_of ('.', uri.count)
p := uri.last_index_of ({CHARACTER_32} '.', uri.count)
if p > 0 then
Result := uri.substring (p + 1, uri.count)
else
create {STRING_8} Result.make_empty
create {STRING_32} Result.make_empty
end
end
real_filename (fn: STRING): STRING
uri_path_to_filename (fn: READABLE_STRING_32): STRING_32
-- Real filename from url-path `fn'
--| Find a better design for this piece of code
--| Eventually in a spec/$ISE_PLATFORM/ specific cluster
local
n: INTEGER
do
if fn.is_empty then
Result := fn
else
n := fn.count
create Result.make_from_string (fn)
if n > 0 and then Result.item (Result.count) = {CHARACTER_32} '/' then
Result.remove_tail (1)
n := n - 1
end
if n > 0 and then Result.item (1) = {CHARACTER_32} '/' then
Result.remove_head (1)
n := n - 1
end
if n > 0 then
if {PLATFORM}.is_windows then
create Result.make_from_string (fn)
Result.replace_substring_all ("/", "\")
if Result [Result.count] = '\' then
Result.remove_tail (1)
end
else
Result := fn
if Result [Result.count] = '/' then
Result.remove_tail (1)
end
Result.replace_substring_all ({STRING_32} "/", {STRING_32} "\")
end
end
end
feature {NONE} -- Implementation
node_exists (p: READABLE_STRING_8): BOOLEAN
local
f: RAW_FILE
do
create f.make (p)
Result := f.exists
end
extension_mime_mapping: HTTP_FILE_EXTENSION_MIME_MAPPING
local
f: RAW_FILE
once
create f.make ("mime.types")
create f.make_with_name ("mime.types")
if f.exists and then f.is_readable then
create Result.make_from_file (f.name)
create Result.make_from_file (f.path.name)
else
create Result.make_default
end
@@ -453,6 +571,11 @@ feature {NONE} -- Implementation
feature {NONE} -- implementation: date time
file_size (f: FILE): INTEGER
do
Result := f.count
end
file_date (f: FILE): DATE_TIME
do
Result := timestamp_to_date (f.date)

View File

@@ -30,10 +30,15 @@ feature -- Execution
handle_unavailable (res)
elseif requires_proxy (req) then
handle_use_proxy (req, res)
elseif maximum_uri_length > 0 and then req.request_uri.count.to_natural_32 > maximum_uri_length then
elseif
maximum_uri_length > 0 and then
req.request_uri.count.to_natural_32 > maximum_uri_length
then
handle_request_uri_too_long (res)
elseif req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then
req.request_uri.same_string ("*") then
elseif
req.is_request_method ({HTTP_REQUEST_METHODS}.method_options) and then
req.request_uri.same_string ("*")
then
handle_server_options (req, res)
else
create l_sess

View File

@@ -77,12 +77,12 @@ feature -- Status
feature -- Helper
path_from_request (req: WSF_REQUEST): READABLE_STRING_32
path_from_request (req: WSF_REQUEST): READABLE_STRING_8
-- Path used by `Current' to check that mapping matches request `req'
require
req_attached: req /= Void
do
Result := req.path_info
Result := req.percent_encoded_path_info
ensure
path_from_request_attached: Result /= Void
end

View File

@@ -10,6 +10,11 @@ class
inherit
WSF_SESSION
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
create
make,
make_new
@@ -128,15 +133,6 @@ feature {NONE} -- Storage
data.compare_objects
end
sessions_folder_name: READABLE_STRING_8
local
dn: DIRECTORY_NAME
once
create dn.make_from_string ((create {EXECUTION_ENVIRONMENT}).current_working_directory)
dn.extend ("_sessions_")
Result := dn.string
end
load
do
if manager.session_exists (uuid) then
@@ -181,7 +177,7 @@ feature {NONE} -- Implementation
end
note
copyright: "Copyright (c) 1984-2012, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -21,12 +21,12 @@ feature {NONE} -- Initialization
make_with_folder ("_WSF_SESSIONS_")
end
make_with_folder (a_folder: like sessions_folder_name)
make_with_folder (a_folder: READABLE_STRING_GENERAL)
do
sessions_folder_name := a_folder
create sessions_folder_name.make_from_string (a_folder)
end
sessions_folder_name: STRING_8
sessions_folder_name: PATH
feature -- Access
@@ -34,7 +34,7 @@ feature -- Access
local
f: RAW_FILE
do
create f.make (file_name (a_session_uuid))
create f.make_with_path (file_name (a_session_uuid))
Result := f.exists and then f.is_readable
end
@@ -42,7 +42,7 @@ feature -- Access
local
f: RAW_FILE
do
create f.make (file_name (a_session_uuid))
create f.make_with_path (file_name (a_session_uuid))
if f.exists and then f.is_readable then
f.open_read
if attached data_from_file (f) as d then
@@ -68,7 +68,7 @@ feature -- Persistence
delete_session (a_session)
else
ensure_session_folder_exists
create f.make (file_name (a_session.uuid))
create f.make_with_path (file_name (a_session.uuid))
if not f.exists or else f.is_writable then
f.create_read_write
a_session.data.set_expiration (a_session.expiration)
@@ -91,7 +91,7 @@ feature -- Persistence
rescued: BOOLEAN
do
if not rescued then
create f.make (file_name (a_session.uuid))
create f.make_with_path (file_name (a_session.uuid))
if f.exists then
f.delete
end
@@ -131,7 +131,7 @@ feature {NONE} -- Implementation
local
d: DIRECTORY
once
create d.make (sessions_folder_name)
create d.make_with_path (sessions_folder_name)
if not d.exists then
d.recursive_create_dir
end
@@ -143,18 +143,13 @@ feature {NONE} -- Implementation
local
d: DIRECTORY
do
create d.make (sessions_folder_name)
create d.make_with_path (sessions_folder_name)
Result := d.exists and then d.is_writable
end
file_name (a_uuid: like {WSF_SESSION}.uuid): READABLE_STRING_8
local
fn: FILE_NAME
file_name (a_uuid: like {WSF_SESSION}.uuid): PATH
do
create fn.make_from_string (sessions_folder_name)
fn.set_file_name (a_uuid.out)
fn.add_extension ("session")
Result := fn.string
Result := sessions_folder_name.extended (a_uuid.out).appended_with_extension ("session")
end
note

View File

@@ -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

View 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

View File

@@ -62,7 +62,7 @@ feature -- Access
url_encoded_name: READABLE_STRING_8
-- URL encoded string of `name'.
do
Result := url_encoder.encoded_string (name)
Result := url_encoded_string (name)
end
values: LIST [WSF_STRING]

View File

@@ -50,20 +50,6 @@ feature -- Access
url_encoded_value: READABLE_STRING_8
-- URL encoded string of `value'.
frozen string: like value
obsolete
"Use value [2012-May-31]"
do
Result := value
end
frozen url_encoded_string: like url_encoded_value
obsolete
"Use url_encoded_value [2012-May-31]"
do
Result := url_encoded_value
end
feature -- Conversion
integer_value: INTEGER
@@ -137,7 +123,7 @@ feature -- Visitor
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -36,17 +36,17 @@ feature -- Access
feature -- Status report
debug_output: STRING
debug_output: STRING_32
-- String that should be displayed in debugger to represent `Current'.
do
Result := Precursor
if
exists and then
attached tmp_name as n
attached tmp_path as p
then
Result.append_character (' ')
Result.append_character ('%"')
Result.append (n)
Result.append (p.name)
Result.append_character ('%"')
end
Result.append (" filename=%"")
@@ -108,14 +108,56 @@ feature -- Access: Uploaded File
size: INTEGER
-- Size of uploaded file
tmp_name: detachable STRING
tmp_path: detachable PATH
-- Filename of tmp file
tmp_name: detachable READABLE_STRING_GENERAL
do
if attached tmp_path as p then
Result := p.name
end
end
tmp_basename: detachable STRING
-- Basename of tmp file
feature -- Conversion
append_content_to_string (a_target: STRING)
-- Append the content of the uploaded file to `a_target'.
local
f: RAW_FILE
s: STRING
done: BOOLEAN
retried: BOOLEAN
do
if not retried and attached tmp_name as fn then
create f.make_with_name (fn)
if f.exists then
f.open_read
from
until
done
loop
f.read_stream_thread_aware (1_024)
s := f.last_string
if s.is_empty then
done := True
else
a_target.append (s)
done := f.exhausted or f.end_of_file
end
end
f.close
end
end
rescue
retried := True
retry
end
feature -- Implementation
safe_filename: STRING
local
fn: like filename
@@ -202,7 +244,7 @@ feature -- Conversion
feature -- Basic operation
move_to (a_destination: STRING): BOOLEAN
move_to (a_destination: READABLE_STRING_GENERAL): BOOLEAN
-- Move current uploaded file to `a_destination'
--| Violates CQS principle.
require
@@ -211,10 +253,10 @@ feature -- Basic operation
local
f: RAW_FILE
do
if attached tmp_name as n then
create f.make (n)
if attached tmp_path as p then
create f.make_with_path (p)
if f.exists then
f.change_name (a_destination)
f.rename_file (a_destination)
Result := True
end
end
@@ -239,8 +281,8 @@ feature -- Status
local
f: PLAIN_TEXT_FILE
do
if attached tmp_name as n then
create f.make (n)
if attached tmp_path as p then
create f.make_with_path (p)
Result := f.exists
end
end
@@ -253,10 +295,19 @@ feature -- Element change
error := e
end
set_tmp_path (p: like tmp_path)
do
tmp_path := p
end
set_tmp_name (n: like tmp_name)
-- Set `tmp_name' to `n'
do
tmp_name := n
if n /= Void then
set_tmp_path (create {PATH}.make_from_string (n))
else
set_tmp_path (Void)
end
end
set_tmp_basename (n: like tmp_basename)

View File

@@ -9,6 +9,13 @@ deferred class
inherit
DEBUG_OUTPUT
SHARED_WSF_PERCENT_ENCODER
rename
percent_encoder as url_encoder
export
{NONE} all
end
feature -- Access
name: READABLE_STRING_32
@@ -91,23 +98,26 @@ feature -- Helper
feature -- Status report
debug_output: STRING
debug_output: STRING_32
-- String that should be displayed in debugger to represent `Current'.
do
create Result.make_from_string (url_encoder.encoded_string (name) + "=" + url_encoder.encoded_string (string_representation))
create Result.make_from_string (name + {STRING_32} "=" + string_representation)
end
feature {NONE} -- Implementation
url_decoded_string (s: READABLE_STRING_8): READABLE_STRING_32
url_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
-- Decoded url-encoded string `s'
do
Result := url_encoder.decoded_string (s)
create Result.make (s.count)
url_encoder.append_percent_encoded_string_to (s, Result)
end
url_encoder: URL_ENCODER
once
create {UTF8_URL_ENCODER} Result --| Chrome is UTF-8 encoding the non ascii in query
url_decoded_string (s: READABLE_STRING_GENERAL): STRING_32
-- Decoded url-encoded string `s'
do
create Result.make (s.count)
url_encoder.append_percent_decoded_string_to (s, Result)
end
feature -- Visitor
@@ -117,7 +127,7 @@ feature -- Visitor
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -24,6 +24,7 @@ feature {NONE} -- Initialization
do
router := a_router
make (req)
set_suggestion_only_method (True)
end
feature -- Access
@@ -36,6 +37,9 @@ feature -- Settings
documentation_included: BOOLEAN
-- Include self-documentation from `router' in the response?
suggestion_only_method: BOOLEAN
-- Display only suggestion for `req' method ?
feature -- Change
set_documentation_included (b: BOOLEAN)
@@ -43,6 +47,14 @@ feature -- Change
documentation_included := b
end
set_suggestion_only_method (b: BOOLEAN)
-- Set `suggestion_only_method' to `b'
do
suggestion_only_method := b
ensure
suggestion_only_method_set: suggestion_only_method = b
end
feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE)
@@ -138,10 +150,14 @@ feature {NONE} -- Implementation
not_found_message (req: WSF_REQUEST): WSF_NOT_FOUND_RESPONSE
local
vis: WSF_ROUTER_AGENT_ITERATOR
l_method: detachable READABLE_STRING_8
do
Result := Precursor (req)
if documentation_included then
create vis
if suggestion_only_method then
l_method := req.request_method
end
vis.on_item_actions.extend (agent (i: WSF_ROUTER_ITEM; r: WSF_NOT_FOUND_RESPONSE; m: detachable READABLE_STRING_8)
local
l_is_hidden: BOOLEAN
@@ -174,7 +190,7 @@ feature {NONE} -- Implementation
r.add_suggested_text (s, Void)
end
end
end (?, Result, req.request_method))
end (?, Result, l_method))
vis.process_router (router)
end
end

View File

@@ -10,6 +10,8 @@ class
inherit
WSF_RESPONSE_MESSAGE
SHARED_UTF8_URL_ENCODER
create
make,
make_with_content_type,
@@ -17,26 +19,26 @@ create
feature {NONE} -- Initialization
make (a_file_name: READABLE_STRING_8)
make (a_file_name: READABLE_STRING_GENERAL)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
file_name := a_file_name
base_name := basename (a_file_name)
create file_path.make_from_string (a_file_name)
base_name := basename (file_path)
get_content_type
initialize
end
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
set_status_code ({HTTP_STATUS_CODE}.ok)
file_name := a_filename
base_name := basename (a_filename)
create file_path.make_from_string (a_filename)
base_name := basename (file_path)
content_type := a_content_type
initialize
end
make_html (a_filename: READABLE_STRING_8)
make_html (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
@@ -45,15 +47,14 @@ feature {NONE} -- Initialization
initialize
local
h: like header
d: HTTP_DATE
do
create h.make
header := h
h.put_content_type (content_type)
h.put_transfer_encoding_binary
h.put_content_length (filesize (file_name))
h.put_content_length (filesize (file_path))
h.put_content_disposition ("attachment", "filename=%""+ base_name +"%"")
if attached filedate (file_name) as dt then
if attached filedate (file_path) as dt then
h.put_last_modified (dt)
end
end
@@ -89,7 +90,14 @@ feature -- Access
status_code: INTEGER assign set_status_code
file_path: PATH
file_name: READABLE_STRING_8
obsolete
"Use `file_path.name' for unicode support [2013-may]"
do
Result := file_path.utf_8_name
end
base_name: READABLE_STRING_8
@@ -125,73 +133,57 @@ feature {WSF_RESPONSE} -- Output
res.set_status_code (status_code)
res.put_header_text (header.string)
if not answer_head_request_method then
send_file_content_to (file_name, res)
send_file_content_to (file_path, res)
end
end
feature {NONE} -- Implementation: file system helper
filesize (fn: STRING): INTEGER
filesize (fn: PATH): INTEGER
-- Size of the file `fn'.
local
f: RAW_FILE
do
create f.make (fn)
create f.make_with_path (fn)
if f.exists then
Result := f.count
end
end
filedate (fn: STRING): detachable DATE_TIME
filedate (fn: PATH): detachable DATE_TIME
-- Size of the file `fn'.
local
f: RAW_FILE
d: HTTP_DATE
do
create f.make (fn)
create f.make_with_path (fn)
if f.exists then
create d.make_from_timestamp (f.date)
Result := d.date_time
end
end
file_extension (fn: STRING): STRING
file_extension (fn: PATH): STRING_32
-- Extension of file `fn'.
local
p: INTEGER
do
p := fn.last_index_of ('.', fn.count)
if p > 0 then
Result := fn.substring (p + 1, fn.count)
if attached fn.extension as ext then
Result := ext
else
create Result.make_empty
end
end
basename (fn: STRING): STRING
basename (fn: PATH): STRING
-- Basename of `fn'.
local
p: INTEGER
s: READABLE_STRING_32
do
p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
if p > 0 then
Result := fn.substring (p + 1, fn.count)
if attached fn.entry as p then
s := p.name
else
Result := fn
end
end
dirname (fn: STRING): STRING
-- Dirname of `fn'.
local
p: INTEGER
do
p := fn.last_index_of ((create {OPERATING_ENVIRONMENT}).Directory_separator, fn.count)
if p > 0 then
Result := fn.substring (1, p - 1)
else
create Result.make_empty
s := fn.name
end
Result := url_encoder.encoded_string (s)
end
feature -- Content-type related
@@ -203,7 +195,7 @@ feature -- Content-type related
m: detachable READABLE_STRING_8
do
create m_map.make_default
m := m_map.mime_type (file_extension (file_name).as_lower)
m := m_map.mime_type (file_extension (file_path).as_lower)
if m = Void then
m := {HTTP_MIME_TYPES}.application_force_download
end
@@ -212,15 +204,15 @@ feature -- Content-type related
feature -- Implementation: output
send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
send_file_content_to (fn: PATH; res: WSF_RESPONSE)
-- Send the content of file `fn'
require
string_not_empty: not fn.is_empty
is_readable: (create {RAW_FILE}.make (fn)).is_readable
is_readable: (create {RAW_FILE}.make_with_path (fn)).is_readable
local
f: RAW_FILE
do
create f.make (fn)
create f.make_with_path (fn)
check f.exists and then f.is_readable end
f.open_read

View File

@@ -11,30 +11,49 @@ inherit
WSF_RESPONSE_MESSAGE
create
make_with_path,
make_with_content_type_and_path,
make_html_with_path,
make,
make_with_content_type,
make_html
feature {NONE} -- Initialization
make (a_file_name: READABLE_STRING_8)
make_with_path (a_path: PATH)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
file_name := a_file_name
file_path := a_path
get_content_type
initialize
end
make_with_content_type (a_content_type: READABLE_STRING_8; a_filename: READABLE_STRING_8)
-- Initialize `Current'.
make_with_content_type_and_path (a_content_type: READABLE_STRING_8; a_path: PATH)
do
set_status_code ({HTTP_STATUS_CODE}.ok)
file_name := a_filename
file_path := a_path
content_type := a_content_type
initialize
end
make_html (a_filename: READABLE_STRING_8)
make_html_with_path (a_path: PATH)
-- Initialize `Current'.
do
make_with_content_type_and_path ({HTTP_MIME_TYPES}.text_html, a_path)
end
make (a_file_name: READABLE_STRING_GENERAL)
do
make_with_path (create {PATH}.make_from_string (a_file_name))
end
make_with_content_type (a_content_type: READABLE_STRING_8; a_file_name: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make_with_content_type_and_path (a_content_type, create {PATH}.make_from_string (a_file_name))
end
make_html (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make_with_content_type ({HTTP_MIME_TYPES}.text_html, a_filename)
@@ -118,13 +137,21 @@ feature -- Access
content_type: READABLE_STRING_8
-- Content-Type of the response
file_path: path
-- File path
file_name: READABLE_STRING_8
obsolete
"Use `file_path.name' for unicode support [2013-may]"
do
Result := file_path.utf_8_name
end
file_exists: BOOLEAN
-- File exists?
file_size: INTEGER
-- Size of file named `file_name'
-- Size of file `file_path'
head, bottom: detachable READABLE_STRING_8
-- Eventual head and bottom part
@@ -184,7 +211,7 @@ feature {WSF_RESPONSE} -- Output
res.put_string (s)
end
if not answer_head_request_method then
send_file_content_to (file_name, res)
send_file_content_to (file_path, res)
end
s := bottom
if s /= Void then
@@ -200,40 +227,37 @@ feature {NONE} -- Implementation: file system helper
local
f: RAW_FILE
do
create f.make (file_name)
create f.make_with_path (file_path)
file_exists := f.exists
end
get_file_size
-- Get `file_size' from file named `file_name'
-- Get `file_size' from file named `file_path'
require
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (file_name)
create f.make_with_path (file_path)
file_size := f.count
end
file_last_modified: detachable DATE_TIME
-- Get `file_size' from file named `file_name'
-- Get `file_size' from file named `file_path'
require
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (file_name)
create f.make_with_path (file_path)
create Result.make_from_epoch (f.change_date)
end
file_extension (fn: STRING): STRING
file_extension (fn: PATH): STRING_32
-- Extension of file `fn'.
local
p: INTEGER
do
p := fn.last_index_of ('.', fn.count)
if p > 0 then
Result := fn.substring (p + 1, fn.count)
if attached fn.extension as ext then
Result := ext
else
create Result.make_empty
end
@@ -242,13 +266,13 @@ feature {NONE} -- Implementation: file system helper
feature -- Content-type related
get_content_type
-- Content type associated with `file_name'
-- Content type associated with `file_path'
local
m_map: HTTP_FILE_EXTENSION_MIME_MAPPING
m: detachable READABLE_STRING_8
do
create m_map.make_default
m := m_map.mime_type (file_extension (file_name).as_lower)
m := m_map.mime_type (file_extension (file_path).as_lower)
if m = Void then
m := {HTTP_MIME_TYPES}.application_force_download
end
@@ -257,16 +281,16 @@ feature -- Content-type related
feature {NONE} -- Implementation: output
send_file_content_to (fn: READABLE_STRING_8; res: WSF_RESPONSE)
send_file_content_to (fn: PATH; res: WSF_RESPONSE)
-- Send the content of file `fn'
require
string_not_empty: not fn.is_empty
is_readable: (create {RAW_FILE}.make (fn)).is_readable
is_readable: (create {RAW_FILE}.make_with_path (fn)).is_readable
file_exists: file_exists
local
f: RAW_FILE
do
create f.make (fn)
create f.make_with_path (fn)
check f.is_readable end
f.open_read

View File

@@ -136,11 +136,11 @@ feature {WSF_RESPONSE} -- Output
s.append (
"[
<style type="text/css">
div#header {color: #fff; background-color: #000; padding: 20px; width: 100%; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; width: 100%; text-align: center; font-size: 1.5em; }
div#header {color: #fff; background-color: #000; padding: 20px; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; text-align: center; font-size: 1.5em; }
div#suggestions { margin: auto; width: 60%;}
div#suggestions ul { }
div#footer {color: #999; background-color: #eee; padding: 10px; width: 100%; text-align: center; }
div#footer {color: #999; background-color: #eee; padding: 10px; text-align: center; }
div#logo { float: right; margin: 20px; width: 60px height: auto; font-size: 0.8em; text-align: center; }
div#logo div.outter { padding: 6px; width: 60px; border: solid 3px #500; background-color: #b00;}
div#logo div.outter div.inner1 { display: block; margin: 10px 15px; width: 30px; height: 50px; color: #fff; background-color: #fff; border: solid 2px #900; }

View File

@@ -81,11 +81,11 @@ feature {WSF_RESPONSE} -- Output
s.append ("</title>%N")
s.append ("[
<style type="text/css">
div#header {color: #fff; background-color: #000; padding: 20px; width: 100%; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; width: 100%; text-align: center; font-size: 1.5em; }
div#header {color: #fff; background-color: #000; padding: 20px; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; text-align: center; font-size: 1.5em; }
div#suggestions { margin: auto; width: 60%;}
div#suggestions ul { }
div#footer {color: #999; background-color: #eee; padding: 10px; width: 100%; text-align: center; }
div#footer {color: #999; background-color: #eee; padding: 10px; text-align: center; }
div#logo { float: right; margin: 20px; width: 60px height: auto; font-size: 0.8em; text-align: center; }
div#logo div.outter { padding: 6px; width: 60px; border: solid 3px #500; background-color: #b00;}
div#logo div.outter div.inner1 { display: block; margin: 10px 15px; width: 30px; height: 50px; color: #fff; background-color: #fff; border: solid 2px #900; }
@@ -198,7 +198,7 @@ feature {WSF_RESPONSE} -- Output
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -53,8 +53,6 @@ feature {WSF_RESPONSE} -- Output
send_to (res: WSF_RESPONSE)
local
s: STRING
l_text: detachable READABLE_STRING_GENERAL
l_loc: detachable READABLE_STRING_8
h: like header
do
h := header
@@ -68,9 +66,9 @@ feature {WSF_RESPONSE} -- Output
s.append ("</title>%N")
s.append ("[
<style type="text/css">
div#header {color: #fff; background-color: #000; padding: 20px; width: 100%; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; width: 100%; text-align: center; font-size: 1.5em; }
div#footer {color: #999; background-color: #eee; padding: 10px; width: 100%; text-align: center; }
div#header {color: #fff; background-color: #000; padding: 20px; text-align: center; font-size: 2em; font-weight: bold;}
div#message { margin: 40px; text-align: center; font-size: 1.5em; }
div#footer {color: #999; background-color: #eee; padding: 10px; text-align: center; }
div#logo { float: right; margin: 20px; width: 60px height: auto; font-size: 0.8em; text-align: center; }
div#logo div.outter { padding: 6px; width: 60px; border: solid 3px #500; background-color: #b00;}
div#logo div.outter div.inner1 { display: block; margin: 10px 15px; width: 30px; height: 50px; color: #fff; background-color: #fff; border: solid 2px #900; }
@@ -117,8 +115,8 @@ feature {WSF_RESPONSE} -- Output
end
note
copyright: "2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -7,45 +7,19 @@ deferred class
WSF_DEFAULT_SERVICE_I [G -> WSF_SERVICE_LAUNCHER create make_and_launch end]
inherit
WSF_SERVICE
WSF_LAUNCHABLE_SERVICE
feature {NONE} -- Initialization
frozen make_and_launch
launch (a_service: WSF_SERVICE; opts: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
local
l_launcher: G
do
initialize
create l_launcher.make_and_launch (Current, service_options)
end
initialize
-- Initialize current service
--| Could be redefine to set custom service option(s)
do
end
service_options: detachable WSF_SERVICE_LAUNCHER_OPTIONS
feature -- Default service options
set_service_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
-- Set options related to WSF_DEFAULT_SERVICE
local
opts: like service_options
do
opts := service_options
if opts = Void then
create opts.make
service_options := opts
end
opts.set_option (a_name, a_value)
ensure
attached service_options as l_options and then l_options.option (a_name) = a_value
create l_launcher.make_and_launch (a_service, opts)
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -15,7 +15,7 @@ class
WSF_SERVICE_LAUNCHER_OPTIONS
inherit
ANY
TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL]
redefine
default_create
end
@@ -23,7 +23,8 @@ inherit
create
default_create,
make,
make_from_array
make_from_array,
make_from_iterable
convert
make_from_array ({ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]]})
@@ -44,6 +45,19 @@ feature {NONE} -- Initialization
make_from_array (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
do
make
append_array_of_options (a_options)
end
make_from_iterable (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
do
make
append_options (a_options)
end
feature -- Merging
append_array_of_options (a_options: ARRAY [TUPLE [name: READABLE_STRING_GENERAL; value: detachable ANY]])
do
across
a_options as opt
loop
@@ -53,6 +67,15 @@ feature {NONE} -- Initialization
end
end
append_options (a_options: TABLE_ITERABLE [detachable ANY, READABLE_STRING_GENERAL])
do
across
a_options as o
loop
set_option (o.key, o.item)
end
end
feature -- Access
option (a_name: READABLE_STRING_GENERAL): detachable ANY
@@ -60,6 +83,14 @@ feature -- Access
Result := options.item (a_name)
end
feature -- Access
new_cursor: TABLE_ITERATION_CURSOR [detachable ANY, READABLE_STRING_GENERAL]
-- Fresh cursor associated with current structure
do
Result := options.new_cursor
end
feature -- Element change
set_option (a_name: READABLE_STRING_GENERAL; a_value: detachable ANY)
@@ -75,13 +106,13 @@ feature -- Element change
feature {NONE} -- Implementation
options: HASH_TABLE [detachable ANY, READABLE_STRING_GENERAL]
options: STRING_TABLE [detachable ANY]
-- Custom options which might be support (or not) by the default service
invariant
options_attached: options /= Void
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -11,28 +11,40 @@ inherit
WSF_SERVICE_LAUNCHER_OPTIONS
create
make_from_file
make_from_file,
make_from_file_and_defaults
feature {NONE} -- Initialization
make_from_file (a_filename: READABLE_STRING_32)
make_from_file (a_filename: READABLE_STRING_GENERAL)
-- Initialize `Current'.
do
make
import (a_filename)
end
make_from_file_and_defaults (a_filename: READABLE_STRING_GENERAL; dft: detachable WSF_SERVICE_LAUNCHER_OPTIONS)
-- Initialize `Current'.
do
make
if dft /= Void then
append_options (dft)
end
import (a_filename)
end
feature {NONE} -- Implementation
import (a_filename: READABLE_STRING_32)
import (a_filename: READABLE_STRING_GENERAL)
-- Import ini file content
local
f: PLAIN_TEXT_FILE
l,v: STRING_8
p: INTEGER
do
--FIXME: handle unicode filename here.
create f.make (a_filename)
create f.make_with_name (a_filename)
if f.exists and f.is_readable then
f.open_read
from
@@ -60,7 +72,7 @@ feature {NONE} -- Implementation
end
note
copyright: "2011-2012, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[
Eiffel Software

View File

@@ -42,6 +42,9 @@ feature {WGI_CONNECTOR} -- Implementation: Execution
w_req.destroy
rescue
if w_res /= Void then
if not (w_res.status_committed or w_res.header_committed) then
w_res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error)
end
w_res.flush
end
if w_req /= Void then

View File

@@ -26,6 +26,18 @@ class
inherit
DEBUG_OUTPUT
SHARED_EXECUTION_ENVIRONMENT
export
{NONE} all
end
SHARED_WSF_PERCENT_ENCODER
rename
percent_encoder as url_encoder
export
{NONE} all
end
create {WSF_TO_WGI_SERVICE}
make_from_wgi
@@ -40,26 +52,25 @@ feature {NONE} -- Initialization
do
wgi_request := r
create string_equality_tester
if attached r.meta_variables as l_vars then
create tb.make_with_key_tester (l_vars.count, string_equality_tester)
create tb.make_equal (l_vars.count)
across
l_vars as c
loop
tb.force (new_string_value (c.key, c.item), c.key)
if attached {READABLE_STRING_8} c.key as s8 then
tb.force (new_string_value (s8, c.item), c.key)
else
tb.force (new_string_value (url_encoded_string (c.key), c.item), c.key)
end
end
else
create tb.make_with_key_tester (0, string_equality_tester)
create tb.make_equal (0)
end
meta_variables_table := tb
meta_variables := tb
create error_handler.make
create uploaded_files_table.make_with_key_tester (0, string_equality_tester)
create uploaded_files_table.make_equal (0)
set_raw_input_data_recorded (False)
create {IMMUTABLE_STRING_32} empty_string.make_empty
create execution_variables_table.make_with_key_tester (0, string_equality_tester)
execution_variables_table.compare_objects
create execution_variables_table.make_equal (0)
initialize
analyze
@@ -96,12 +107,13 @@ feature {NONE} -- Initialization
request_method := req.request_method
--| PATH_INFO
path_info := raw_url_encoder.decoded_string (req.path_info)
percent_encoded_path_info := req.path_info
path_info := url_decoded_string (req.path_info)
--| PATH_TRANSLATED
s8 := req.path_translated
if s8 /= Void then
path_translated := raw_url_encoder.decoded_string (s8)
path_translated := url_decoded_string (s8)
end
--| Here one can set its own environment entries if needed
@@ -111,6 +123,7 @@ feature {NONE} -- Initialization
end
wgi_request: WGI_REQUEST
-- Associated WGI request
feature -- Destroy
@@ -125,6 +138,26 @@ feature -- Destroy
loop
delete_uploaded_file (c.item)
end
content_length_value := 0
content_type := Void
execution_variables_table.wipe_out
internal_cookies_table := Void
internal_form_data_parameters_table := Void
internal_query_parameters_table := Void
internal_server_url := Void
internal_url_base := Void
form_parameters_table.wipe_out
mime_handlers := Void
path_info := empty_string_32
path_parameters_source := Void
path_parameters_table := Void
path_translated := Void
raw_input_data := Void
raw_input_data_recorded := False
request_method := empty_string_8
set_uploaded_file_path (Void)
-- wgi_request
end
feature -- Status report
@@ -199,17 +232,16 @@ feature -- Access: Input
local
l_input: WGI_INPUT_STREAM
n: INTEGER
s: STRING
do
if raw_input_data_recorded and then attached raw_input_data as d then
buf.copy (d)
buf.append (d)
else
l_input := input
if is_chunked_input then
from
n := 8_192
until
n = 0
n = 0 or l_input.end_of_input
loop
l_input.append_to_string (buf, n)
if l_input.last_appended_count < n then
@@ -230,6 +262,47 @@ feature -- Access: Input
end
end
read_input_data_into_file (a_file: FILE)
-- retrieve the content from the `input' stream into `s'
-- warning: if the input data has already been retrieved
-- you might not get anything
require
a_file_is_open_write: a_file.is_open_write
local
s: STRING
l_input: WGI_INPUT_STREAM
l_raw_data: detachable STRING_8
n: INTEGER
do
if raw_input_data_recorded and then attached raw_input_data as d then
a_file.put_string (d)
else
if raw_input_data_recorded then
create l_raw_data.make_empty
end
l_input := input
from
n := 8_192
create s.make (n)
until
n = 0 or l_input.end_of_input
loop
l_input.append_to_string (s, n)
a_file.put_string (s)
if l_raw_data /= Void then
l_raw_data.append (s)
end
s.wipe_out
if l_input.last_appended_count < n then
n := 0
end
end
if l_raw_data /= Void then
set_raw_input_data (l_raw_data)
end
end
end
feature -- Helper
is_request_method (m: READABLE_STRING_GENERAL): BOOLEAN
@@ -313,12 +386,12 @@ feature {WSF_REQUEST_EXPORTER} -- Override value
feature {NONE} -- Access: global variable
items_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
items_table: STRING_TABLE [WSF_VALUE]
-- Table containing all the various variables
-- Warning: this is computed each time, if you change the content of other containers
-- this won't update this Result's content, unless you query it again
do
create Result.make_with_key_tester (20, string_equality_tester)
create Result.make_equal (20)
if attached path_parameters as l_path_parameters then
across
@@ -486,6 +559,14 @@ feature -- Helpers: global variables
feature -- Execution variables
has_execution_variable (a_name: READABLE_STRING_GENERAL): BOOLEAN
-- Has execution variable related to `a_name'?
require
a_name_valid: a_name /= Void and then not a_name.is_empty
do
Result := execution_variables_table.has (a_name)
end
execution_variable (a_name: READABLE_STRING_GENERAL): detachable ANY
-- Execution variable related to `a_name'
require
@@ -510,7 +591,7 @@ feature -- Execution variables
feature {NONE} -- Execution variables: implementation
execution_variables_table: HASH_TABLE_EX [detachable ANY, READABLE_STRING_GENERAL]
execution_variables_table: STRING_TABLE [detachable ANY]
feature -- Access: CGI Meta variables
@@ -534,6 +615,9 @@ feature -- Access: CGI Meta variables
meta_variables: ITERABLE [WSF_STRING]
-- CGI meta variables values
do
Result := meta_variables_table
end
meta_string_variable_or_default (a_name: READABLE_STRING_GENERAL; a_default: READABLE_STRING_32; use_default_when_empty: BOOLEAN): READABLE_STRING_32
-- Value for meta parameter `a_name'
@@ -569,7 +653,7 @@ feature -- Access: CGI Meta variables
feature {NONE} -- Access: CGI meta parameters
meta_variables_table: HASH_TABLE_EX [WSF_STRING, READABLE_STRING_GENERAL]
meta_variables_table: STRING_TABLE [WSF_STRING]
-- CGI Environment parameters
feature -- Access: CGI meta parameters - 1.1
@@ -691,6 +775,11 @@ feature -- Access: CGI meta parameters - 1.1
Result := wgi_request.gateway_interface
end
percent_encoded_path_info: READABLE_STRING_8
-- Non decoded PATH_INFO value from CGI.
-- See `path_info' for the related percent decoded value.
--| This value should be used by component dealing only with ASCII path
path_info: READABLE_STRING_32
-- The PATH_INFO metavariable specifies a path to be interpreted
-- by the CGI script. It identifies the resource or sub-resource
@@ -719,6 +808,8 @@ feature -- Access: CGI meta parameters - 1.1
-- The PATH_INFO value is case-sensitive, and the server MUST
-- preserve the case of the PATH_INFO element of the URI when
-- making it available to scripts.
--
-- See `percent_encoded_path_info' to get the original non decoded path info.
path_translated: detachable READABLE_STRING_32
-- PATH_TRANSLATED is derived by taking any path-info component
@@ -1138,7 +1229,7 @@ feature -- Cookies
feature {NONE} -- Cookies
cookies_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
cookies_table: STRING_TABLE [WSF_VALUE]
-- Expanded cookies variable
local
i,j,p,n: INTEGER
@@ -1149,8 +1240,7 @@ feature {NONE} -- Cookies
if l_cookies = Void then
if attached {WSF_STRING} meta_variable ({WSF_META_NAMES}.http_cookie) as val then
s := val.value
create l_cookies.make_with_key_tester (5, string_equality_tester)
l_cookies.compare_objects
create l_cookies.make_equal (5)
from
n := s.count
p := 1
@@ -1178,8 +1268,7 @@ feature {NONE} -- Cookies
end
end
else
create l_cookies.make_with_key_tester (0, string_equality_tester)
l_cookies.compare_objects
create l_cookies.make_equal (0)
end
internal_cookies_table := l_cookies
end
@@ -1205,7 +1294,7 @@ feature -- Path parameters
feature {NONE} -- Query parameters: implementation
path_parameters_table: detachable HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
path_parameters_table: detachable STRING_TABLE [WSF_VALUE]
-- Parameters computed from `path_parameters_source'
--| most often coming from the associated route from WSF_ROUTER
@@ -1228,8 +1317,7 @@ feature {WSF_REQUEST_PATH_PARAMETERS_SOURCE} -- Path parameters: Element change
if l_count = 0 then
l_table := Void
else
create l_table.make_with_key_tester (l_count, string_equality_tester)
l_table.compare_objects
create l_table.make_equal (l_count)
if attached src.path_parameters as tb then
across
tb as c
@@ -1266,7 +1354,7 @@ feature -- Query parameters
feature {NONE} -- Query parameters: implementation
query_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
query_parameters_table: STRING_TABLE [WSF_VALUE]
-- Parameters extracted from QUERY_STRING
local
vars: like internal_query_parameters_table
@@ -1291,13 +1379,12 @@ feature {NONE} -- Query parameters: implementation
end
end
vars := urlencoded_parameters (s)
vars.compare_objects
internal_query_parameters_table := vars
end
Result := vars
end
urlencoded_parameters (a_content: detachable READABLE_STRING_8): HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
urlencoded_parameters (a_content: detachable READABLE_STRING_8): STRING_TABLE [WSF_VALUE]
-- Import `a_content'
local
n, p, i, j: INTEGER
@@ -1305,13 +1392,13 @@ feature {NONE} -- Query parameters: implementation
l_name, l_value: READABLE_STRING_8
do
if a_content = Void then
create Result.make_with_key_tester (0, string_equality_tester)
create Result.make_equal (0)
else
n := a_content.count
if n = 0 then
create Result.make_with_key_tester (0, string_equality_tester)
create Result.make_equal (0)
else
create Result.make_with_key_tester (3, string_equality_tester) --| 3 = arbitrary value
create Result.make_equal (3) --| 3 = arbitrary value
from
p := 1
until
@@ -1336,6 +1423,8 @@ feature {NONE} -- Query parameters: implementation
end
end
end
ensure
result_with_object_comparison: Result.object_comparison
end
feature -- Form fields and related
@@ -1440,7 +1529,7 @@ feature {NONE} -- Implementation: MIME handler
feature {NONE} -- Form fields and related
uploaded_files_table: HASH_TABLE_EX [WSF_UPLOADED_FILE, READABLE_STRING_GENERAL]
uploaded_files_table: STRING_TABLE [WSF_UPLOADED_FILE]
get_form_parameters
-- Variables sent by POST, ... request
@@ -1452,14 +1541,12 @@ feature {NONE} -- Form fields and related
vars := internal_form_data_parameters_table
if vars = Void then
if not is_chunked_input and content_length_value = 0 then
create vars.make_with_key_tester (0, string_equality_tester)
vars.compare_objects
create vars.make_equal (0)
else
if raw_input_data_recorded then
create l_raw_data_cell.put (Void)
end
create vars.make_with_key_tester (5, string_equality_tester)
vars.compare_objects
create vars.make_equal (5)
l_type := content_type
if l_type /= Void and then attached mime_handler (l_type) as hdl then
@@ -1476,7 +1563,7 @@ feature {NONE} -- Form fields and related
internal_form_data_parameters_table /= Void
end
form_parameters_table: HASH_TABLE_EX [WSF_VALUE, READABLE_STRING_GENERAL]
form_parameters_table: STRING_TABLE [WSF_VALUE]
-- Variables sent by POST request
local
vars: like internal_form_data_parameters_table
@@ -1485,14 +1572,14 @@ feature {NONE} -- Form fields and related
vars := internal_form_data_parameters_table
if vars = Void then
check form_parameters_already_retrieved: False end
create vars.make_with_key_tester (0, string_equality_tester)
create vars.make_equal (0)
end
Result := vars
end
feature {NONE} -- Implementation: smart parameter identification
add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: HASH_TABLE [WSF_VALUE, READABLE_STRING_GENERAL])
add_value_to_table (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8; a_table: STRING_TABLE [WSF_VALUE])
-- Add urlencoded parameter `a_name'=`a_value' to `a_table'
-- following smart computation such as handling the "..[..]" as table
local
@@ -1536,7 +1623,7 @@ feature {NONE} -- Implementation: smart parameter identification
if p > 0 then
q := r.index_of ({CHARACTER_8} ']', p + 1)
if q > p then
k32 := url_encoder.decoded_string (k)
k32 := url_decoded_string (k)
if attached {WSF_TABLE} ptb.value (k32) as l_tb_value then
tb := l_tb_value
else
@@ -1598,7 +1685,7 @@ feature -- Uploaded File Handling
until
l_files.after or Result
loop
if attached l_files.item_for_iteration.tmp_name as l_tmp_name and then l_tmp_name.same_string_general (a_filename) then
if attached l_files.item_for_iteration.tmp_path as l_tmp_path and then a_filename.same_string (l_tmp_path.name) then
Result := True
end
l_files.forth
@@ -1674,7 +1761,7 @@ feature -- URL Utility
elseif spos > 0 then
i := spos
end
spos := l_rq_uri.substring_index (path_info, i)
spos := l_rq_uri.substring_index (percent_encoded_path_info, i)
if spos > 0 then
l_base_url := l_rq_uri.substring (1, spos - 1)
else
@@ -1714,7 +1801,7 @@ feature -- Element change
error_handler := ehdl
end
feature {WSF_MIME_HANDLER} -- Temporary File handling
feature {WSF_MIME_HANDLER} -- Temporary File handling
delete_uploaded_file (uf: WSF_UPLOADED_FILE)
-- Delete file `a_filename'
@@ -1724,18 +1811,18 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
f: RAW_FILE
do
if uploaded_files_table.has_item (uf) then
if attached uf.tmp_name as fn then
create f.make (fn)
if attached uf.tmp_path as fn then
create f.make_with_path (fn)
if f.exists and then f.is_writable then
f.delete
else
error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete file %""+ fn +"%"")
error_handler.add_custom_error (0, "Can not delete uploaded file", {STRING_32} "Can not delete file %""+ fn.name + {STRING_32} "%"")
end
else
error_handler.add_custom_error (0, "Can not delete uploaded file", "Can not delete uploaded file %""+ uf.name +"%" Tmp File not found")
error_handler.add_custom_error (0, "Can not delete uploaded file", {STRING_32} "Can not delete uploaded file %""+ uf.name + {STRING_32} "%" Tmp File not found")
end
else
error_handler.add_custom_error (0, "Not an uploaded file", "This file %""+ uf.name +"%" is not an uploaded file.")
error_handler.add_custom_error (0, "Not an uploaded file", {STRING_32} "This file %""+ uf.name + {STRING_32} "%" is not an uploaded file.")
end
end
@@ -1745,37 +1832,39 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
bn: STRING
l_safe_name: STRING
f: RAW_FILE
dn: STRING
fn: FILE_NAME
dn: PATH
fn: PATH
d: DIRECTORY
n: INTEGER
rescued: BOOLEAN
do
if not rescued then
-- FIXME: should it be configured somewhere?
dn := (create {EXECUTION_ENVIRONMENT}).current_working_directory
create d.make (dn)
if attached uploaded_file_path as p then
dn := p
else
-- FIXME: should it be configured somewhere?
dn := execution_environment.current_working_path
end
create d.make_with_path (dn)
if d.exists and then d.is_writable then
l_safe_name := a_up_file.safe_filename
from
create fn.make_from_string (dn)
bn := "tmp-" + l_safe_name
fn.set_file_name (bn)
create f.make (fn.string)
fn := dn.extended (bn)
create f.make_with_path (fn)
n := 0
until
not f.exists
or else n > 1_000
loop
n := n + 1
fn.make_from_string (dn)
bn := "tmp-" + n.out + "-" + l_safe_name
fn.set_file_name (bn)
f.make (fn.string)
fn := dn.extended (bn)
f.make_with_path (fn)
end
if not f.exists or else f.is_writable then
a_up_file.set_tmp_name (f.name)
a_up_file.set_tmp_path (f.path)
a_up_file.set_tmp_basename (bn)
f.open_write
f.put_string (a_content)
@@ -1784,7 +1873,7 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
a_up_file.set_error (-1)
end
else
error_handler.add_custom_error (0, "Directory not writable", "Can not create file in directory %""+ dn +"%"")
error_handler.add_custom_error (0, "Directory not writable", {STRING_32} "Can not create file in directory %""+ dn.name + {STRING_32} "%"")
end
uploaded_files_table.force (a_up_file, a_up_file.name)
else
@@ -1795,6 +1884,19 @@ feature {WSF_MIME_HANDLER} -- Temporary File handling
retry
end
feature {WSF_REQUEST_EXPORTER} -- Settings
uploaded_file_path: detachable PATH
-- Optional folder path used to store uploaded files
set_uploaded_file_path (p: like uploaded_file_path)
-- Set `uploaded_file_path' to `p'.
require
path_exists: p /= Void implies (create {DIRECTORY}.make_with_path (p)).exists
do
uploaded_file_path := p
end
feature {NONE} -- Internal value
internal_query_parameters_table: detachable like query_parameters_table
@@ -1845,8 +1947,6 @@ feature {NONE} -- Implementation
feature {NONE} -- Implementation: utilities
string_equality_tester: STRING_EQUALITY_TESTER
single_slash_starting_string (s: READABLE_STRING_32): STRING_32
-- Return the string `s' (or twin) with one and only one starting slash
local
@@ -1898,17 +1998,27 @@ feature {NONE} -- Implementation: utilities
create Result.make (a_name, a_value)
end
empty_string: READABLE_STRING_32
empty_string_32: IMMUTABLE_STRING_32
-- Reusable empty string
raw_url_encoder: URL_ENCODER
once
create {URL_ENCODER} Result
create Result.make_empty
end
url_encoder: URL_ENCODER
empty_string_8: IMMUTABLE_STRING_8
once
create {UTF8_URL_ENCODER} Result
create Result.make_empty
end
url_encoded_string (s: READABLE_STRING_GENERAL): STRING_8
do
create Result.make (s.count)
url_encoder.append_percent_encoded_string_to (s, Result)
end
url_decoded_string (s: READABLE_STRING_GENERAL): STRING_32
do
create Result.make (s.count)
url_encoder.append_percent_decoded_string_to (s, Result)
end
date_time_utilities: HTTP_DATE_TIME_UTILITIES
@@ -1918,7 +2028,8 @@ feature {NONE} -- Implementation: utilities
end
invariant
empty_string_unchanged: empty_string.is_empty
empty_string_32_unchanged: empty_string_32.is_empty
empty_string_8_unchanged: empty_string_8.is_empty
wgi_request.content_type /= Void implies content_type /= Void
note

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-10-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-10-0 http://www.eiffel.com/developers/xml/configuration-1-10-0.xsd" name="wsf" uuid="A37CE5AA-4D2A-4441-BC6A-0A1D7EC49647" library_target="wsf">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf" uuid="A37CE5AA-4D2A-4441-BC6A-0A1D7EC49647" library_target="wsf">
<target name="wsf">
<root all_classes="true"/>
<file_rule>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_extension" uuid="11055B92-CBEF-4272-8B50-0450BDA154E5" library_target="wsf_extension">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_extension" uuid="11055B92-CBEF-4272-8B50-0450BDA154E5" library_target="wsf_extension">
<target name="wsf_extension">
<root all_classes="true"/>
<file_rule>
@@ -9,11 +9,11 @@
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
<library name="http" location="../../network/protocol/http/http-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\network\protocol\http\http-safe.ecf"/>
<library name="wsf" location="wsf-safe.ecf"/>
<library name="wsf_router_context" location="wsf_router_context-safe.ecf" readonly="true"/>
<cluster name="extension" location="./extension" recursive="true"/>
<cluster name="extension" location=".\extension\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-9-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-9-0 http://www.eiffel.com/developers/xml/configuration-1-9-0.xsd" name="wsf_router_context" uuid="1A0F9B0E-26CE-4DE0-BE47-C74D1AB2B389" library_target="wsf_router_context">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_router_context" uuid="1A0F9B0E-26CE-4DE0-BE47-C74D1AB2B389" library_target="wsf_router_context">
<target name="wsf_router_context">
<root all_classes="true"/>
<file_rule>
@@ -11,6 +11,6 @@
</option>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="wsf" location="wsf-safe.ecf"/>
<cluster name="router_context" location=".\router_context" recursive="true"/>
<cluster name="router_context" location=".\router_context\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_session" uuid="C41D0367-9852-4AA7-9E7E-DEA162A4CBB0" library_target="wsf_session">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_session" uuid="C41D0367-9852-4AA7-9E7E-DEA162A4CBB0" library_target="wsf_session">
<target name="wsf_session">
<root all_classes="true"/>
<file_rule>
@@ -9,12 +9,12 @@
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY/library/time/time-safe.ecf"/>
<library name="uuid" location="$ISE_LIBRARY/library/uuid/uuid-safe.ecf"/>
<library name="http" location="../../network/protocol/http/http-safe.ecf"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="ewsgi" location="..\ewsgi\ewsgi-safe.ecf"/>
<library name="http" location="..\..\network\protocol\http\http-safe.ecf"/>
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
<library name="uuid" location="$ISE_LIBRARY\library\uuid\uuid-safe.ecf"/>
<library name="wsf-safe" location="wsf-safe.ecf"/>
<cluster name="session" location="./session" recursive="true"/>
<cluster name="session" location=".\session\" recursive="true"/>
</target>
</system>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-8-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-8-0 http://www.eiffel.com/developers/xml/configuration-1-8-0.xsd" name="wsf_html" uuid="6AAAE037-7E66-4F5D-BED0-0042245C26BC" library_target="wsf_html">
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-11-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-11-0 http://www.eiffel.com/developers/xml/configuration-1-11-0.xsd" name="wsf_html" uuid="6AAAE037-7E66-4F5D-BED0-0042245C26BC" library_target="wsf_html">
<target name="wsf_html">
<root all_classes="true"/>
<file_rule>
@@ -9,13 +9,13 @@
</file_rule>
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="all" syntax="standard">
</option>
<library name="base" location="$ISE_LIBRARY/library/base/base-safe.ecf"/>
<library name="encoder" location="../../text/encoder/encoder-safe.ecf"/>
<library name="uri_template" location="../../text/parser/uri_template/uri_template-safe.ecf"/>
<library name="wsf" location="../wsf/wsf-safe.ecf"/>
<cluster name="form" location="./form" recursive="true"/>
<cluster name="widget" location="./widget" recursive="true"/>
<cluster name="css" location="./css" recursive="true"/>
<cluster name="api" location="./api" recursive="true"/>
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
<library name="encoder" location="..\..\text\encoder\encoder-safe.ecf"/>
<library name="uri_template" location="..\..\text\parser\uri_template\uri_template-safe.ecf"/>
<library name="wsf" location="..\wsf\wsf-safe.ecf"/>
<cluster name="api" location=".\api\" recursive="true"/>
<cluster name="css" location=".\css\" recursive="true"/>
<cluster name="form" location=".\form\" recursive="true"/>
<cluster name="widget" location=".\widget\" recursive="true"/>
</target>
</system>