Compare commits

..
Author SHA1 Message Date
Jocelyn Fiat c83b9d4231 Updated CHANGELOG.md 2017-05-17 17:38:25 +02:00
Jocelyn Fiat 69b5ce637e Improved query and form data encoding (based on a very early version of the general URI percent-encoding rules).
- now correct encoding of space by '%20' in path segment, and '+' in query parameters.
Unify and fixed query parameters handling for libcurl and net implementation.
Fixed file uploading (various issue in libcurl, and net implementation).
Fixed form multipart encoding by using correctly the boundary.
Updated autotest cases.
Code cleaning.
2017-05-17 12:16:35 +02:00
Jocelyn Fiat 485a3812d9 Integrated recent changes on SOCKET.socket_buffer splitted as read_socket_buffer and put_socket_buffer. 2017-05-15 12:20:52 +02:00
Jocelyn Fiat 88dec34a1e Made "common" targets as abstract. 2017-05-12 14:39:48 +02:00
Jocelyn Fiat a928f27b1a Updated or added timestamp to obsolete and fixme messages.
Fixed ecf file exclusion for .svn and .git .
Cosmetic changed.
2017-05-12 14:31:35 +02:00
Jocelyn Fiat 7ba678d726 Added empty .travis.yml for now (see https://travis-ci.com/) 2017-04-14 13:32:37 +02:00
64 changed files with 1152 additions and 284 deletions
View File
+24
View File
@@ -8,12 +8,36 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
## [Unreleased] ## [Unreleased]
### Added ### Added
### Changed ### Changed
- http_network:
Integrated changes on SOCKET so that EiffelWeb can be compiled with 16.05 to 17.05 and after.
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed
- http_client:
Improved query and form data encoding (based on a very early version of the general URI percent-encoding rules).
- now correct encoding of space by '%20' in path segment, and '+' in query parameters.
Unify and fixed query parameters handling for libcurl and net implementation.
Fixed file uploading (various issue in libcurl, and net implementation).
Fixed form multipart encoding by using correctly the boundary.
- Code cleaning:
Removed many obsolete calls, and added timestamp on EiffelWeb obsolete features to benefit from upcoming improvement on the EiffelStudio Inspector tool.
### Security ### Security
## [v1.0.5] - 2017-05-17
### Changed
- http_network:
Integrated changes on SOCKET so that EiffelWeb can be compiled with 16.05 to 17.05 and after.
### Fixed
- http_client:
Improved query and form data encoding (based on a very early version of the general URI percent-encoding rules).
- now correct encoding of space by '%20' in path segment, and '+' in query parameters.
Unify and fixed query parameters handling for libcurl and net implementation.
Fixed file uploading (various issue in libcurl, and net implementation).
Fixed form multipart encoding by using correctly the boundary.
- Code cleaning:
Removed many obsolete calls, and added timestamp on EiffelWeb obsolete features to benefit from upcoming improvement on the EiffelStudio Inspector tool.
## [v1.0.4] - 2017-03-15 ## [v1.0.4] - 2017-03-15
### Added ### Added
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="filter" uuid="52FF4B77-0614-4D8B-9B96-C07EC852793E"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="filter" uuid="52FF4B77-0614-4D8B-9B96-C07EC852793E">
<target name="common"> <target name="common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="filter" uuid="52FF4B77-0614-4D8B-9B96-C07EC852793E"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="filter" uuid="52FF4B77-0614-4D8B-9B96-C07EC852793E">
<target name="common"> <target name="common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
@@ -84,7 +84,7 @@ feature {NONE} -- Initialization
create l_methods create l_methods
l_methods.enable_options l_methods.enable_options
l_methods.enable_get l_methods.enable_get
router.handle_with_request_methods ("/user/{userid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent l_options_filter.execute), l_methods) router.handle ("/user/{userid}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent l_options_filter.execute), l_methods)
end end
initialize_json initialize_json
@@ -99,7 +99,7 @@ feature {NONE} -- Implementation
-- Port number -- Port number
note note
copyright: "2011-2014, Olivier Ligot, Jocelyn Fiat and others" copyright: "2011-2017, Olivier Ligot, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -42,7 +42,7 @@ feature -- Basic operations
id : STRING id : STRING
do do
if attached req.orig_path_info as orig_path then if attached req.orig_path_info as orig_path then
id := get_user_id_from_path (orig_path) id := get_user_id_from_path (orig_path.as_string_32)
if attached retrieve_user (id) as l_user then if attached retrieve_user (id) as l_user then
if l_user ~ req.execution_variable ("user") then if l_user ~ req.execution_variable ("user") then
compute_response_get (req, res, l_user) compute_response_get (req, res, l_user)
@@ -92,6 +92,6 @@ feature {NONE} -- Implementation
end end
note note
copyright: "2011-2013, Olivier Ligot, Jocelyn Fiat and others" copyright: "2011-2017, Olivier Ligot, Jocelyn Fiat and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
end end
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="restbucks" uuid="2773FEAA-448F-410E-BEDE-9298C4749066"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="restbucks" uuid="2773FEAA-448F-410E-BEDE-9298C4749066">
<target name="restbucks_common"> <target name="restbucks_common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
@@ -85,7 +85,6 @@ feature {NONE} -- Initialization
create_order (sess: HTTP_CLIENT_SESSION) : HTTP_CLIENT_RESPONSE create_order (sess: HTTP_CLIENT_SESSION) : HTTP_CLIENT_RESPONSE
local local
s: READABLE_STRING_8 s: READABLE_STRING_8
j: JSON_PARSER
context : HTTP_CLIENT_REQUEST_CONTEXT context : HTTP_CLIENT_REQUEST_CONTEXT
do do
s := "[ s := "[
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="restbucks" uuid="2773FEAA-448F-410E-BEDE-9298C4749066"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="restbucks" uuid="2773FEAA-448F-410E-BEDE-9298C4749066">
<target name="restbucks_common"> <target name="restbucks_common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
@@ -4,7 +4,8 @@ note
date: "$Date$" date: "$Date$"
revision: "$Revision$" revision: "$Revision$"
class ORDER_HANDLER class
ORDER_HANDLER
inherit inherit
@@ -537,7 +538,6 @@ feature {NONE} -- Conversion
order_to_json (obj: ORDER): JSON_OBJECT order_to_json (obj: ORDER): JSON_OBJECT
local local
j_order: JSON_OBJECT
j_item: JSON_OBJECT j_item: JSON_OBJECT
ja: JSON_ARRAY ja: JSON_ARRAY
do do
@@ -19,8 +19,6 @@ create
feature {NONE} -- Initialization feature {NONE} -- Initialization
make make
local
b: SED_MEMORY_READER_WRITER
do do
create collections.make (0) create collections.make (0)
end end
@@ -86,8 +84,6 @@ feature {NONE} -- Implementation
next_identifier (a_entry_type: TYPE [detachable ANY]): STRING_8 next_identifier (a_entry_type: TYPE [detachable ANY]): STRING_8
local local
i: INTEGER i: INTEGER
f: RAW_FILE
s: STRING
tb: detachable STRING_TABLE [detachable ANY] tb: detachable STRING_TABLE [detachable ANY]
do do
tb := collections.item (a_entry_type) tb := collections.item (a_entry_type)
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="upload_image" uuid="F2400BE8-D8EB-48EB-B4E4-5D4377062A7F"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="upload_image" uuid="F2400BE8-D8EB-48EB-B4E4-5D4377062A7F">
<target name="upload_image_common"> <target name="upload_image_common" abstract="true">
<file_rule> <file_rule>
<exclude>/EIFGENs$</exclude> <exclude>/EIFGENs$</exclude>
<exclude>/\.git$</exclude> <exclude>/\.git$</exclude>
@@ -33,6 +33,7 @@
</library> </library>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/> <library name="uri" location="$ISE_LIBRARY\library\text\uri\uri-safe.ecf"/>
<cluster name="src" location=".\src\"> <cluster name="src" location=".\src\">
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
<cluster name="spec_null" location="$|spec\null\" recursive="true"/> <cluster name="spec_null" location="$|spec\null\" recursive="true"/>
<cluster name="spec_net" location="$|spec\net\"> <cluster name="spec_net" location="$|spec\net\">
<condition> <condition>
@@ -33,6 +33,7 @@
</library> </library>
<library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/> <library name="uri" location="$ISE_LIBRARY\library\text\uri\uri.ecf"/>
<cluster name="src" location=".\src\"> <cluster name="src" location=".\src\">
<cluster name="implementation" location="$|implementation" recursive="true" hidden="true"/>
<cluster name="spec_null" location="$|spec\null\" recursive="true"/> <cluster name="spec_null" location="$|spec\null\" recursive="true"/>
<cluster name="spec_net" location="$|spec\net\"> <cluster name="spec_net" location="$|spec\net\">
<condition> <condition>
@@ -196,73 +196,8 @@ feature -- Settings
Result := session.is_insecure Result := session.is_insecure
end end
feature {NONE} -- Utilities
append_parameters_to_url (a_parameters: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]; a_url: STRING)
-- Append parameters `a_parameters' to `a_url'
require
a_url_attached: a_url /= Void
local
l_first_param: BOOLEAN
do
if a_parameters.count > 0 then
if a_url.index_of ('?', 1) > 0 then
l_first_param := False
elseif a_url.index_of ('&', 1) > 0 then
l_first_param := False
else
l_first_param := True
end
from
a_parameters.start
until
a_parameters.after
loop
if l_first_param then
a_url.append_character ('?')
else
a_url.append_character ('&')
end
a_url.append (urlencode (a_parameters.key_for_iteration))
a_url.append_character ('=')
a_url.append (urlencode (a_parameters.item_for_iteration))
l_first_param := False
a_parameters.forth
end
end
end
feature {NONE} -- Utilities: encoding
url_encoder: URL_ENCODER
once
create Result
end
urlencode (s: READABLE_STRING_32): READABLE_STRING_8
-- URL encode `s'
do
Result := url_encoder.encoded_string (s)
end
urldecode (s: READABLE_STRING_8): READABLE_STRING_32
-- URL decode `s'
do
Result := url_encoder.decoded_string (s)
end
stripslashes (s: STRING): STRING
do
Result := s.string
Result.replace_substring_all ("\%"", "%"")
Result.replace_substring_all ("\'", "'")
Result.replace_substring_all ("\/", "/")
Result.replace_substring_all ("\\", "\")
end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -13,7 +13,7 @@ note
Note that any value set in this context class overrides conflicting value eventually Note that any value set in this context class overrides conflicting value eventually
set in associated HTTP_CLIENT_SESSION. set in associated HTTP_CLIENT_SESSION.
Warning: for now [2012-May], you can have only one of the following data Warning: for now [2012-05-31], you can have only one of the following data
- form_parameters - form_parameters
- or upload_data - or upload_data
- or upload_filename - or upload_filename
@@ -142,16 +142,16 @@ feature -- Element change
end end
end end
add_query_parameter (k: READABLE_STRING_32; v: READABLE_STRING_32) add_query_parameter (k: READABLE_STRING_GENERAL; v: READABLE_STRING_GENERAL)
-- Add a query parameter `k=v'. -- Add a query parameter `k=v'.
do do
query_parameters.force (v, k) query_parameters.force (v.to_string_32, k.to_string_32)
end end
add_form_parameter (k: READABLE_STRING_32; v: READABLE_STRING_32) add_form_parameter (k: READABLE_STRING_GENERAL; v: READABLE_STRING_GENERAL)
-- Add a form parameter `k'= `v'. -- Add a form parameter `k'= `v'.
do do
form_parameters.force (v, k) form_parameters.force (v.to_string_32, k.to_string_32)
end end
set_credentials_required (b: BOOLEAN) set_credentials_required (b: BOOLEAN)
@@ -236,18 +236,62 @@ feature -- Status setting
end end
end end
feature -- URL helpers
append_query_parameters_to_url (a_url: STRING)
-- Append parameters `a_parameters' to `a_url'
require
a_url_attached: a_url /= Void
local
l_first_param: BOOLEAN
do
if
attached query_parameters as l_query_parameters and then
not l_query_parameters.is_empty
then
if a_url.index_of ('?', 1) > 0 then
l_first_param := False
elseif a_url.index_of ('&', 1) > 0 then
l_first_param := False
else
l_first_param := True
end
across
query_parameters as ic
loop
if l_first_param then
a_url.append_character ('?')
else
a_url.append_character ('&')
end
l_first_param := False
uri_percent_encoder.append_query_name_encoded_string_to (ic.key, a_url)
a_url.append_character ('=')
uri_percent_encoder.append_query_value_encoded_string_to (ic.item, a_url)
end
end
end
feature -- Conversion helpers feature -- Conversion helpers
query_parameters_to_url_encoded_string: STRING_8 query_parameters_to_url_encoded_string: STRING_8
-- `query_parameters' as url-encoded string. -- `query_parameters' as url-encoded string.
do do
Result := parameters_to_url_encoded_string (query_parameters) Result := parameters_to_uri_percent_encoded_string (query_parameters)
end
form_parameters_to_x_www_form_url_encoded_string: STRING_8
-- `form_parameters' as x-www-form-urlencoded string.
do
Result := parameters_to_x_www_form_urlencoded_string (form_parameters)
end end
form_parameters_to_url_encoded_string: STRING_8 form_parameters_to_url_encoded_string: STRING_8
-- `form_parameters' as url-encoded string. -- `form_parameters' as url-encoded string.
obsolete "Use form_parameters_to_x_www_form_url_encoded_string [2017-05-31]"
do do
Result := parameters_to_url_encoded_string (form_parameters) Result := form_parameters_to_x_www_form_url_encoded_string
end end
feature {NONE} -- Implementation feature {NONE} -- Implementation
@@ -271,6 +315,52 @@ feature {NONE} -- Implementation
end end
end end
parameters_to_uri_percent_encoded_string (ht: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING_8
-- Build query urlencoded string using parameters from `ht'.
do
create Result.make (64)
across
ht as ic
loop
if not Result.is_empty then
Result.append_character ('&')
end
uri_percent_encoder.append_query_name_encoded_string_to (ic.key, Result)
Result.append_character ('=')
uri_percent_encoder.append_query_value_encoded_string_to (ic.item, Result)
end
end
parameters_to_x_www_form_urlencoded_string (ht: HASH_TABLE [READABLE_STRING_32, READABLE_STRING_32]): STRING_8
-- Build x-www-form-urlencoded string using parameters from `ht'.
do
create Result.make (64)
from
ht.start
until
ht.after
loop
if not Result.is_empty then
Result.append_character ('&')
end
Result.append (x_www_form_url_encoder.encoded_string (ht.key_for_iteration))
Result.append_character ('=')
Result.append (x_www_form_url_encoder.encoded_string (ht.item_for_iteration))
ht.forth
end
end
x_www_form_url_encoder: X_WWW_FORM_URL_ENCODER
-- Shared x-www-form-urlencoded encoder.
once
create Result
end
uri_percent_encoder: URI_PERCENT_ENCODER
once
create Result
end
url_encoder: URL_ENCODER url_encoder: URL_ENCODER
-- Shared URL encoder. -- Shared URL encoder.
once once
@@ -278,7 +368,7 @@ feature {NONE} -- Implementation
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -60,28 +60,10 @@ feature -- Access
url (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): STRING_8 url (a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): STRING_8
-- Url computed from Current and `ctx' data. -- Url computed from Current and `ctx' data.
local
s: STRING_8
url_encoder: URL_ENCODER
do do
Result := base_url + a_path Result := base_url + a_path
if ctx /= Void then if ctx /= Void then
create s.make_empty ctx.append_query_parameters_to_url (Result)
create url_encoder
across
ctx.query_parameters as q
loop
if not s.is_empty then
s.append_character ('&')
end
s.append (url_encoder.encoded_string (q.key))
s.append_character ('=')
s.append (url_encoder.encoded_string (q.item))
end
if not s.is_empty then
Result.append_character ('?')
Result.append (s)
end
end end
end end
@@ -420,7 +402,7 @@ feature -- Element change
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -0,0 +1,628 @@
note
description: "[
Component to handle percent encoding
WARNING: THIS IS A COPY FROM $ISE_LIBRARY/library/text/uri library.
In the future, http_client will use directly the `uri` library.
]"
date: "$Date$"
revision: "$Revision$"
EIS: "name=Percent-encoding", "protocol=URI", "src=http://en.wikipedia.org/wiki/Percent-encoding"
class
URI_PERCENT_ENCODER
feature -- Percent encoding
append_percent_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
-- Append `s' as percent-encoded value to `a_result'
local
i,n: INTEGER
do
from
i := 1
n := s.count
until
i > n
loop
append_encoded_character_code_to (s.code (i), a_result)
i := i + 1
end
end
append_query_name_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
-- Append `s' as encoded for URI query name to `a_result'
local
i,n: INTEGER
do
from
i := 1
n := s.count
until
i > n
loop
append_query_name_encoded_character_code_to (s.code (i), a_result)
i := i + 1
end
end
append_query_value_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
-- Append `s' as encoded for URI query value to `a_result'.
local
i,n: INTEGER
do
from
i := 1
n := s.count
until
i > n
loop
append_query_value_encoded_character_code_to (s.code (i), a_result)
i := i + 1
end
end
append_path_segment_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
-- Append `a_string' as encoded for URI path segment to `a_result'
local
i,n: INTEGER
do
from
i := 1
n := s.count
until
i > n
loop
append_path_segment_encoded_character_code_to (s.code (i), a_result)
i := i + 1
end
end
append_www_form_url_encoded_string_to (s: READABLE_STRING_GENERAL; a_result: STRING_GENERAL)
-- Append `a_string' as www-form-urlencoded value to `a_result'.
-- The main difference with `append_percent_encoded_string_to` is the encoding of space using '+'.
local
i,n: INTEGER
do
from
i := 1
n := s.count
until
i > n
loop
inspect s.code (i)
when 32 then -- space: 32 ' '
a_result.append_code (43) -- 43 '+'
else
append_encoded_character_code_to (s.code (i), a_result)
end
i := i + 1
end
end
feature {NONE} -- URI building helpers
append_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
-- Append character code `c' as query name encoded content into `a_result'.
do
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
end
append_query_name_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
-- Append character code `a_code' as query name encoded content into `a_result'.
do
inspect c
when 61 then -- equal sign: =
append_percent_encoded_character_code_to (c, a_result)
else
append_query_value_encoded_character_code_to (c, a_result)
end
end
append_query_value_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
-- Append character code `a_code' as query value encoded content into `a_result'.
do
inspect c
when 32 then -- Space
a_result.append_code (43) -- 43 '+'
when
39, -- '
58, 64, -- reserved =+ gen-delims: : @
33, 36, 40, 41, 42, -- reserved =+ sub-delims: ! $ ( ) *
44, 59, 61 -- reserved = sub-delims: , ; =
then
a_result.append_code (c)
when
47, -- slash: /
63 -- question mark ?
then
a_result.append_code (c)
else
append_encoded_character_code_to (c, a_result)
end
end
append_path_segment_encoded_character_code_to (c: NATURAL_32; a_result: STRING_GENERAL)
-- Append character code `a_code' as query name encoded content into `a_result'.
do
append_encoded_character_code_to (c, a_result)
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
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
-- Keep the percent encoded char for non string 32.
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-2017, Jocelyn Fiat, Javier Velilla, 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
@@ -82,9 +82,6 @@ feature -- Execution
--| URL --| URL
l_url := url l_url := url
if ctx /= Void then
append_parameters_to_url (ctx.query_parameters, l_url)
end
if session.is_header_sent_verbose then if session.is_header_sent_verbose then
io.error.put_string ("> Sending:%N") io.error.put_string ("> Sending:%N")
@@ -171,7 +168,7 @@ feature -- Execution
then then
if l_ct.starts_with ("application/x-www-form-urlencoded") then if l_ct.starts_with ("application/x-www-form-urlencoded") then
-- Content-Type is already application/x-www-form-urlencoded -- Content-Type is already application/x-www-form-urlencoded
l_upload_data := ctx.form_parameters_to_url_encoded_string l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
elseif l_ct.starts_with ("multipart/form-data") then elseif l_ct.starts_with ("multipart/form-data") then
l_use_curl_form := True l_use_curl_form := True
else else
@@ -179,7 +176,7 @@ feature -- Execution
l_use_curl_form := True l_use_curl_form := True
end end
else else
l_upload_data := ctx.form_parameters_to_url_encoded_string l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
end end
else else
l_use_curl_form := True l_use_curl_form := True
@@ -199,6 +196,14 @@ feature -- Execution
) )
l_form_data.forth l_form_data.forth
end end
if l_upload_filename /= Void then
curl.formadd_string_string (l_form, l_last,
{CURL_FORM_CONSTANTS}.curlform_copyname, "file",
{CURL_FORM_CONSTANTS}.curlform_file, l_upload_filename,
{CURL_FORM_CONSTANTS}.curlform_end
)
l_upload_filename := Void
end
l_last.release_item l_last.release_item
curl_easy.setopt_form (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httppost, l_form) curl_easy.setopt_form (curl_handle, {CURL_OPT_CONSTANTS}.curlopt_httppost, l_form)
end end
@@ -41,7 +41,7 @@ feature -- Custom
local local
req: HTTP_CLIENT_REQUEST req: HTTP_CLIENT_REQUEST
do do
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx) create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
Result := req.response Result := req.response
end end
@@ -154,7 +154,7 @@ feature {NONE} -- Implementation
end end
end end
create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx) create {LIBCURL_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
Result := req.response Result := req.response
if f /= Void then if f /= Void then
@@ -176,7 +176,7 @@ feature {LIBCURL_HTTP_CLIENT_REQUEST} -- Curl implementation
;note ;note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -9,7 +9,7 @@ class
LIBCURL_UPLOAD_FILE_READ_FUNCTION LIBCURL_UPLOAD_FILE_READ_FUNCTION
obsolete obsolete
"Use LIBCURL_CUSTOM_FUNCTION [2013-apr-04]" "Use LIBCURL_CUSTOM_FUNCTION [2017-05-31]"
inherit inherit
LIBCURL_DEFAULT_FUNCTION LIBCURL_DEFAULT_FUNCTION
@@ -156,7 +156,7 @@ feature -- Access
end end
create l_request_uri.make_from_string (l_uri.path) create l_request_uri.make_from_string (l_uri.path)
if attached l_uri.query as l_query then if attached l_uri.query as l_query and then not l_query.is_empty then
l_request_uri.append_character ('?') l_request_uri.append_character ('?')
l_request_uri.append (l_query) l_request_uri.append (l_query)
end end
@@ -198,7 +198,7 @@ feature -- Access
attached headers.item ("Content-Type") as l_ct attached headers.item ("Content-Type") as l_ct
then then
if l_ct.starts_with ("application/x-www-form-urlencoded") then if l_ct.starts_with ("application/x-www-form-urlencoded") then
l_upload_data := ctx.form_parameters_to_url_encoded_string l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
elseif l_ct.starts_with ("multipart/form-data") then elseif l_ct.starts_with ("multipart/form-data") then
-- create form using multipart/form-data encoding -- create form using multipart/form-data encoding
l_boundary := new_mime_boundary (l_form_data) l_boundary := new_mime_boundary (l_form_data)
@@ -208,12 +208,12 @@ feature -- Access
-- not supported ! -- not supported !
-- Send as form-urlencoded -- Send as form-urlencoded
headers.extend ("application/x-www-form-urlencoded", "Content-Type") headers.extend ("application/x-www-form-urlencoded", "Content-Type")
l_upload_data := ctx.form_parameters_to_url_encoded_string l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
end end
else else
-- Send as form-urlencoded -- Send as form-urlencoded
headers.extend ("application/x-www-form-urlencoded", "Content-Type") headers.extend ("application/x-www-form-urlencoded", "Content-Type")
l_upload_data := ctx.form_parameters_to_url_encoded_string l_upload_data := ctx.form_parameters_to_x_www_form_url_encoded_string
end end
headers.extend (l_upload_data.count.out, "Content-Length") headers.extend (l_upload_data.count.out, "Content-Length")
if l_is_chunked_transfer_encoding then if l_is_chunked_transfer_encoding then
@@ -246,7 +246,7 @@ feature -- Access
elseif l_upload_filename /= Void then elseif l_upload_filename /= Void then
check ctx.has_upload_filename end check ctx.has_upload_filename end
create l_upload_file.make_with_name (l_upload_filename) create l_upload_file.make_with_name (l_upload_filename)
if l_upload_file.exists and then l_upload_file.readable then if l_upload_file.exists and then l_upload_file.is_access_readable then
if not l_is_chunked_transfer_encoding then if not l_is_chunked_transfer_encoding then
headers.extend (l_upload_file.count.out, "Content-Length") headers.extend (l_upload_file.count.out, "Content-Length")
end end
@@ -495,6 +495,7 @@ feature {NONE} -- Helpers
across across
a_form_parameters as ic a_form_parameters as ic
loop loop
Result.append ("--")
Result.append (a_mime_boundary) Result.append (a_mime_boundary)
Result.append (http_end_of_header_line) Result.append (http_end_of_header_line)
Result.append ("Content-Disposition: form-data; name=") Result.append ("Content-Disposition: form-data; name=")
@@ -519,7 +520,7 @@ feature {NONE} -- Helpers
else else
l_mime_type := "application/octet-stream" l_mime_type := "application/octet-stream"
end end
Result.append ("--")
Result.append (a_mime_boundary) Result.append (a_mime_boundary)
Result.append (http_end_of_header_line) Result.append (http_end_of_header_line)
Result.append ("Content-Disposition: form-data; name=%"") Result.append ("Content-Disposition: form-data; name=%"")
@@ -542,6 +543,7 @@ feature {NONE} -- Helpers
end end
Result.append (http_end_of_header_line) Result.append (http_end_of_header_line)
end end
Result.append ("--")
Result.append (a_mime_boundary) Result.append (a_mime_boundary)
Result.append ("--") --| end Result.append ("--") --| end
end end
@@ -907,7 +909,7 @@ feature {NONE} -- Helpers
create ran.set_seed (i) -- FIXME: use a real random seed. create ran.set_seed (i) -- FIXME: use a real random seed.
ran.start ran.start
ran.forth ran.forth
n := (20 * ran.real_item).truncated_to_integer n := (10 * ran.real_item).truncated_to_integer
create Result.make_filled ('-', 3 + n) create Result.make_filled ('-', 3 + n)
s := "_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" s := "_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
from from
@@ -67,7 +67,7 @@ feature -- Custom
local local
req: HTTP_CLIENT_REQUEST req: HTTP_CLIENT_REQUEST
do do
create {NET_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx) create {NET_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
Result := req.response Result := req.response
end end
@@ -167,12 +167,12 @@ feature {NONE} -- Implementation
end end
end end
create {NET_HTTP_CLIENT_REQUEST} req.make (base_url + a_path, a_method, Current, ctx) create {NET_HTTP_CLIENT_REQUEST} req.make (url (a_path, ctx), a_method, Current, ctx)
Result := req.response Result := req.response
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -25,7 +25,7 @@ feature -- Custom
custom (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE custom (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT): HTTP_CLIENT_RESPONSE
do do
create Result.make (base_url + a_path) create Result.make (url (a_path, ctx))
end end
custom_with_upload_data (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: READABLE_STRING_8): HTTP_CLIENT_RESPONSE custom_with_upload_data (a_method: READABLE_STRING_8; a_path: READABLE_STRING_8; a_ctx: detachable HTTP_CLIENT_REQUEST_CONTEXT; data: READABLE_STRING_8): HTTP_CLIENT_RESPONSE
@@ -98,7 +98,7 @@ feature -- Status report
-- Is interface usable? -- Is interface usable?
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -34,6 +34,11 @@ feature -- Tests
test_post_with_form_data test_post_with_form_data
end end
libcurl_test_post_with_uncommon_form_data
do
test_post_with_uncommon_form_data
end
libcurl_test_post_with_file libcurl_test_post_with_file
do do
test_post_with_file test_post_with_file
@@ -34,6 +34,11 @@ feature -- Tests
test_post_with_form_data test_post_with_form_data
end end
net_test_post_with_uncommon_form_data
do
test_post_with_uncommon_form_data
end
net_test_post_with_file net_test_post_with_file
do do
test_post_with_file test_post_with_file
@@ -69,4 +74,9 @@ feature -- Tests
test_post_with_file_using_chunked_transfer_encoding test_post_with_file_using_chunked_transfer_encoding
end end
net_test_get_with_query_parameters
do
test_get_with_query_parameters
end
end end
@@ -1,4 +1,4 @@
note note
description: "[ description: "[
Eiffel tests that can be executed by testing tool. Eiffel tests that can be executed by testing tool.
]" ]"
@@ -21,7 +21,10 @@ feature -- Initialization
on_prepare on_prepare
do do
Precursor Precursor
global_requestbin_path := new_requestbin_path global_requestbin_path := "/s0jkhhs0"
if global_requestbin_path = Void then
global_requestbin_path := new_requestbin_path
end
end end
feature -- Factory feature -- Factory
@@ -49,6 +52,9 @@ feature -- Requestbin
i := l_content.substring_index ("%"name%":", 1) i := l_content.substring_index ("%"name%":", 1)
if i > 0 then if i > 0 then
j := l_content.index_of (',', i + 1) j := l_content.index_of (',', i + 1)
if j = 0 then
j := l_content.index_of ('}', i + 1)
end
if j > 0 then if j > 0 then
Result := l_content.substring (i + 7, j - 1) Result := l_content.substring (i + 7, j - 1)
Result.adjust Result.adjust
@@ -61,6 +67,7 @@ feature -- Requestbin
if not Result.starts_with ("/") then if not Result.starts_with ("/") then
Result.prepend_character ('/') Result.prepend_character ('/')
end end
print ("new_requestbin_path => http://requestb.in" + Result + "?inspect%N")
end end
end end
end end
@@ -108,8 +115,55 @@ feature -- Factory
-- check requestbin to ensure the form parameters are correctly received -- check requestbin to ensure the form parameters are correctly received
sess := new_session ("http://requestb.in") sess := new_session ("http://requestb.in")
create l_ctx.make create l_ctx.make
l_ctx.form_parameters.extend ("First Value", "First Key") l_ctx.add_form_parameter ("First Key", "First Value")
l_ctx.form_parameters.extend ("Second Value", "Second Key") l_ctx.add_form_parameter ("Second Key", "Second Value")
l_ctx.add_form_parameter ("unicode", {STRING_32} "Hello / 你好 !")
l_ctx.add_form_parameter ({STRING_32} "Field 你好 !", "How are you?")
create h.make_empty
if
attached sess.post (requestbin_path, l_ctx, "") as res and then
attached res.headers as hds
then
across
hds as c
loop
h.append (c.item.name + ": " + c.item.value + "%R%N")
end
end
print (h)
else
assert ("Has requestbin path", False)
end
end
test_post_with_uncommon_form_data
local
sess: HTTP_CLIENT_SESSION
h: STRING_8
l_ctx: HTTP_CLIENT_REQUEST_CONTEXT
do
if attached global_requestbin_path as requestbin_path then
-- POST REQUEST WITH FORM DATA
-- check requestbin to ensure the form parameters are correctly received
sess := new_session ("http://requestb.in")
create l_ctx.make
l_ctx.add_form_parameter ("title", "Eiffel World!") -- space and !
l_ctx.add_form_parameter ("path", "foo/bar") -- slash
l_ctx.add_form_parameter ("unreserved", ":!@[]{}()*") -- ...
l_ctx.add_form_parameter ("reserved", "+=?&_#_") -- ...
l_ctx.add_form_parameter ("a=b", "a=b") -- equal sign
l_ctx.add_form_parameter ("test", "!$&'()*") --
l_ctx.add_form_parameter ("lst[a][b]", "[123][456]") -- brackets
l_ctx.add_form_parameter ("pos{1,2}", "loc{a,b}") -- curly brackets
l_ctx.add_form_parameter ("?foo", "?bar") -- question mark
l_ctx.add_form_parameter ("?", "?") -- question mark
l_ctx.add_form_parameter ("&bar", "&bar") -- ampersand
l_ctx.add_form_parameter ("&", "&") -- ampersand
assert ("form data well generated", l_ctx.form_parameters_to_x_www_form_url_encoded_string.same_string ("title=Eiffel+World!&path=foo%%2Fbar&unreserved=%%3A!%%40%%5B%%5D%%7B%%7D()*&reserved=%%2B%%3D%%3F%%26_%%23_&a%%3Db=a%%3Db&test=!%%24%%26'()*&lst%%5Ba%%5D%%5Bb%%5D=%%5B123%%5D%%5B456%%5D&pos%%7B1%%2C2%%7D=loc%%7Ba%%2Cb%%7D&%%3Ffoo=%%3Fbar&%%3F=%%3F&%%26bar=%%26bar&%%26=%%26"))
create h.make_empty create h.make_empty
if if
attached sess.post (requestbin_path, l_ctx, "") as res and then attached sess.post (requestbin_path, l_ctx, "") as res and then
@@ -143,7 +197,7 @@ feature -- Factory
l_ctx.set_upload_filename ("test.txt") l_ctx.set_upload_filename ("test.txt")
create h.make_empty create h.make_empty
if if
attached sess.post (requestbin_path, l_ctx, "") as res and then attached sess.post (requestbin_path, l_ctx, Void) as res and then
attached res.headers as hds attached res.headers as hds
then then
across across
@@ -202,7 +256,7 @@ feature -- Factory
-- set filename to a local file -- set filename to a local file
sess := new_session ("http://requestb.in") sess := new_session ("http://requestb.in")
create l_ctx.make create l_ctx.make
l_ctx.set_upload_data ("This is a test for http client.%N") l_ctx.set_upload_data ("name=This is a test for http client.%N")
create h.make_empty create h.make_empty
if if
attached sess.put (requestbin_path, l_ctx, Void) as res and then attached sess.put (requestbin_path, l_ctx, Void) as res and then
@@ -232,10 +286,12 @@ feature -- Factory
-- check requestbin to ensure the file and form parameters are correctly received -- check requestbin to ensure the file and form parameters are correctly received
-- set filename to a local file -- set filename to a local file
sess := new_session ("http://requestb.in") sess := new_session ("http://requestb.in")
-- sess := new_session ("http://localhost:9090")
create l_ctx.make create l_ctx.make
l_ctx.set_upload_filename ("logo.jpg") -- l_ctx.set_upload_filename ("logo.jpg")
l_ctx.form_parameters.extend ("First Value", "First Key") l_ctx.set_upload_filename ("test.txt")
l_ctx.form_parameters.extend ("Second Value", "Second Key") l_ctx.add_form_parameter ("First", "Value")
l_ctx.add_form_parameter ("Second", "and last value")
create h.make_empty create h.make_empty
if if
attached sess.post (requestbin_path, l_ctx, Void) as res and then attached sess.post (requestbin_path, l_ctx, Void) as res and then
@@ -297,6 +353,7 @@ feature -- Factory
sess := new_session ("http://google.com") sess := new_session ("http://google.com")
create h.make_empty create h.make_empty
if attached sess.get ("/", Void) as res and then attached res.headers as hds then if attached sess.get ("/", Void) as res and then attached res.headers as hds then
assert("was redirected", res.redirections_count > 0)
across across
hds as c hds as c
loop loop
@@ -328,6 +385,53 @@ feature -- Factory
end end
end end
test_get_with_query_parameters
local
sess: HTTP_CLIENT_SESSION
h: STRING_8
l_ctx: HTTP_CLIENT_REQUEST_CONTEXT
q: STRING
do
if attached global_requestbin_path as requestbin_path then
-- GET REQUEST WITH A FILE AND FORM DATA
-- check requestbin to ensure the file and form parameters are correctly received
-- set filename to a local file
sess := new_session ("http://requestb.in")
create l_ctx.make
l_ctx.add_query_parameter ("?", "?first&arg")
l_ctx.add_query_parameter ("title", "Eiffel World!")
l_ctx.add_query_parameter ("path", "foo/bar")
l_ctx.add_query_parameter ("reserved", "+=&?")
l_ctx.add_query_parameter ("unreserved", ":!@'()*")
l_ctx.add_query_parameter ("unsafe", "%"[]{}")
l_ctx.add_query_parameter ("test", "!$&'()*")
l_ctx.add_query_parameter ("a&b", "a&b")
l_ctx.add_query_parameter ("lst[a][b]", "[abc][123]")
l_ctx.add_query_parameter ("foo(a,b)", "bar(1,2)*pi")
create q.make_empty
l_ctx.append_query_parameters_to_url (q)
assert("query", q.same_string ("??=?first%%26arg&title=Eiffel+World!&path=foo/bar&reserved=%%2B=%%26?&unreserved=:!@'()*&unsafe=%%22%%5B%%5D%%7B%%7D&test=!$%%26'()*&a%%26b=a%%26b&lst%%5Ba%%5D%%5Bb%%5D=%%5Babc%%5D%%5B123%%5D&foo(a,b)=bar(1,2)*pi"))
create h.make_empty
if
attached sess.get (requestbin_path, l_ctx) as res and then
attached res.headers as hds
then
across
hds as c
loop
h.append (c.item.name + ": " + c.item.value + "%R%N")
end
end
print (h)
else
assert ("Has requestbin path", False)
end
end
end end
@@ -58,7 +58,7 @@
<file_rule> <file_rule>
<exclude>/http_stream_socket_ext.e$</exclude> <exclude>/http_stream_socket_ext.e$</exclude>
<condition> <condition>
<version type="compiler" max="16.9.9.9124"/> <version type="compiler" max="17.02"/>
</condition> </condition>
</file_rule> </file_rule>
<cluster name="disabled_ssl_network" location="$|no_ssl\" recursive="true"> <cluster name="disabled_ssl_network" location="$|no_ssl\" recursive="true">
@@ -114,6 +114,11 @@
</condition> </condition>
</cluster> </cluster>
</cluster> </cluster>
<cluster name="network_until_17_01" location=".\src\until_17_01\">
<condition>
<version type="compiler" min="16.9.9.9124" max="17.02"/>
</condition>
</cluster>
</target> </target>
<target name="http_network_ssl" extends="http_network"> <target name="http_network_ssl" extends="http_network">
<variable name="ssl_enabled" value="true"/> <variable name="ssl_enabled" value="true"/>
@@ -58,7 +58,7 @@
<file_rule> <file_rule>
<exclude>/http_stream_socket_ext.e$</exclude> <exclude>/http_stream_socket_ext.e$</exclude>
<condition> <condition>
<version type="compiler" max="16.9.9.9124"/> <version type="compiler" max="17.02"/>
</condition> </condition>
</file_rule> </file_rule>
<cluster name="disabled_ssl_network" location="$|no_ssl\" recursive="true"> <cluster name="disabled_ssl_network" location="$|no_ssl\" recursive="true">
@@ -114,6 +114,11 @@
</condition> </condition>
</cluster> </cluster>
</cluster> </cluster>
<cluster name="network_until_17_01" location=".\src\until_17_01\">
<condition>
<version type="compiler" min="16.9.9.9124" max="17.02"/>
</condition>
</cluster>
</target> </target>
<target name="http_network_ssl" extends="http_network"> <target name="http_network_ssl" extends="http_network">
<variable name="ssl_enabled" value="true"/> <variable name="ssl_enabled" value="true"/>
@@ -36,13 +36,13 @@ feature -- Input
-- Make result available in `last_character'. -- Make result available in `last_character'.
-- No exception raised! -- No exception raised!
do do
read_to_managed_pointer_noexception (socket_buffer, 0, character_8_bytes) read_to_managed_pointer_noexception (read_socket_buffer, 0, character_8_bytes)
if was_error then if was_error then
-- Socket error already set. -- Socket error already set.
elseif bytes_read /= character_8_bytes then elseif bytes_read /= character_8_bytes then
socket_error := "Peer closed connection" socket_error := "Peer closed connection"
else else
last_character := socket_buffer.read_character (0) last_character := read_socket_buffer.read_character (0)
socket_error := Void socket_error := Void
end end
end end
@@ -208,8 +208,8 @@ feature -- Output
put_character_noexception (c: CHARACTER) put_character_noexception (c: CHARACTER)
-- Write character `c' to socket. -- Write character `c' to socket.
do do
socket_buffer.put_character (c, 0) put_socket_buffer.put_character (c, 0)
put_managed_pointer_noexception (socket_buffer, 0, character_8_bytes) put_managed_pointer_noexception (put_socket_buffer, 0, character_8_bytes)
end end
put_string_8_noexception (s: READABLE_STRING_8) put_string_8_noexception (s: READABLE_STRING_8)
@@ -244,7 +244,7 @@ feature -- Status report
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -2,12 +2,20 @@ note
description: "[ description: "[
Extension to HTTPD_STREAM_SOCKET to support backward compatibility. Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
TO BE REMOVED IN THE FUTURE, WHEN 16.05 IS OLD. TO BE REMOVED IN THE FUTURE, When there is no need to support older compilers.
]" ]"
deferred class deferred class
HTTP_STREAM_SOCKET_EXT HTTP_STREAM_SOCKET_EXT
feature {NONE} -- No-Exception network operation note
copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, 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 end
@@ -51,6 +51,20 @@ feature -- Access
deferred deferred
end end
socket_buffer: MANAGED_POINTER
deferred
end
read_socket_buffer: MANAGED_POINTER
do
Result := socket_buffer
end
put_socket_buffer: MANAGED_POINTER
do
Result := socket_buffer
end
feature -- Socket Recv and Send timeout. feature -- Socket Recv and Send timeout.
set_recv_timeout (a_timeout_seconds: INTEGER) set_recv_timeout (a_timeout_seconds: INTEGER)
@@ -0,0 +1,29 @@
note
description: "[
Extension to HTTPD_STREAM_SOCKET to support backward compatibility.
TO BE REMOVED IN THE FUTURE, WHEN 17.01 IS OLD.
]"
deferred class
HTTP_STREAM_SOCKET_EXT
feature -- Access
socket_buffer: MANAGED_POINTER
deferred
end
read_socket_buffer: MANAGED_POINTER
do
Result := socket_buffer
end
put_socket_buffer: MANAGED_POINTER
do
Result := socket_buffer
end
feature {NONE} -- No-Exception network operation
end
@@ -114,14 +114,14 @@ feature -- Obsolete query
include_max_age: BOOLEAN include_max_age: BOOLEAN
obsolete obsolete
"Use `max_age > 0' [April-2016]" "Use `max_age > 0' [2017-05-31]"
do do
Result := max_age > 0 Result := max_age > 0
end end
include_expires: BOOLEAN include_expires: BOOLEAN
obsolete obsolete
"Use `expires /= Void' [April-2016]" "Use `expires /= Void' [2017-05-31]"
do do
Result := expiration /= Void Result := expiration /= Void
end end
@@ -133,7 +133,7 @@ feature -- Obsolete element change
-- Set `expires to void' -- Set `expires to void'
-- Set-Cookie will include only Max-Age attribute and not Expires. -- Set-Cookie will include only Max-Age attribute and not Expires.
obsolete obsolete
"Uset `set_max_age' and `unset_*' features to add or remove the attributes from the response header [April-2016]" "Uset `set_max_age' and `unset_*' features to add or remove the attributes from the response header [2017-05-31]"
do do
max_age := 1 max_age := 1
expiration := Void expiration := Void
@@ -147,7 +147,7 @@ feature -- Obsolete element change
-- Set `expiration to a default date' -- Set `expiration to a default date'
-- Set-Cookie will include only Expires attribute and not Max_Age. -- Set-Cookie will include only Expires attribute and not Max_Age.
obsolete obsolete
"Use `set_expiration' and `unset_*' features to add or remove the attribute from the response header [April-2016]" "Use `set_expiration' and `unset_*' features to add or remove the attribute from the response header [2017-05-31]"
do do
max_age := -1 max_age := -1
set_expiration_date (create {DATE_TIME}.make_now_utc) set_expiration_date (create {DATE_TIME}.make_now_utc)
@@ -343,7 +343,7 @@ feature {NONE} -- Constants
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -118,7 +118,7 @@ feature -- Access
header_named_value (a_name: READABLE_STRING_8): like item header_named_value (a_name: READABLE_STRING_8): like item
-- First header item found for `a_name' if any -- First header item found for `a_name' if any
obsolete obsolete
"Use `item' [2014-03]" "Use `item' [2017-05-31]"
do do
Result := item (a_name) Result := item (a_name)
end end
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="ws_client" uuid="AF6EDC56-D7B4-4E1F-A62B-40EBED3D93DF"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="ws_client" uuid="AF6EDC56-D7B4-4E1F-A62B-40EBED3D93DF">
<target name="common"> <target name="common" abstract="true">
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/.git$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="echo_websocket_server" uuid="C9B3DA5F-DF0D-4C0F-924A-130B5C1E6604"> <system xmlns="http://www.eiffel.com/developers/xml/configuration-1-15-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-15-0 http://www.eiffel.com/developers/xml/configuration-1-15-0.xsd" name="echo_websocket_server" uuid="C9B3DA5F-DF0D-4C0F-924A-130B5C1E6604">
<target name="common"> <target name="common" abstract="true">
<file_rule> <file_rule>
<exclude>/.git$</exclude> <exclude>/.git$</exclude>
<exclude>/.svn$</exclude> <exclude>/.svn$</exclude>
@@ -55,7 +55,7 @@ feature -- Access
body: like content body: like content
obsolete obsolete
"Use `content' [June/2015]" "Use `content'. [2017-05-31]"
do do
Result := body Result := body
end end
@@ -69,6 +69,19 @@ feature -- Status report
across to_addresses as ic all is_valid_address (ic.item) end across to_addresses as ic all is_valid_address (ic.item) end
end end
has_header (a_header_name: READABLE_STRING_8): BOOLEAN
-- Has additional header `a_header_name'?
-- Warning: it checks only `additional_header_lines'!
local
h_colon: STRING
do
if attached additional_header_lines as lst then
create h_colon.make_from_string (a_header_name)
h_colon.append_character (':')
Result := across lst as ic some ic.item.starts_with (h_colon) end
end
end
feature -- Change feature -- Change
set_date (d: like date) set_date (d: like date)
@@ -158,21 +171,6 @@ feature -- Header manipulation
lst.force (a_line) lst.force (a_line)
end end
feature -- Status report
has_header (a_header_name: READABLE_STRING_8): BOOLEAN
-- Has additional header `a_header_name'?
-- Warning: it checks only `additional_header_lines'!
local
h_colon: STRING
do
if attached additional_header_lines as lst then
create h_colon.make_from_string (a_header_name)
h_colon.append_character (':')
Result := across lst as ic some ic.item.starts_with (h_colon) end
end
end
feature -- Reset feature -- Reset
reset reset
@@ -209,8 +207,6 @@ feature -- Conversion
end end
header: STRING_8 header: STRING_8
local
hdate: HTTP_DATE
do do
create Result.make (20) create Result.make (20)
if attached reply_to_address as l_reply_to then if attached reply_to_address as l_reply_to then
@@ -259,8 +255,7 @@ feature -- Conversion
Result.append (subject) Result.append (subject)
Result.append_character ('%N') Result.append_character ('%N')
Result.append ("Date: ") Result.append ("Date: ")
create hdate.make_from_date_time (date) ;(create {HTTP_DATE}.make_from_date_time (date)).append_to_rfc1123_string (Result)
hdate.append_to_rfc1123_string (Result)
Result.append_character ('%N') Result.append_character ('%N')
if attached additional_header_lines as l_lines and then if attached additional_header_lines as l_lines and then
not l_lines.is_empty not l_lines.is_empty
@@ -285,11 +280,8 @@ feature -- Helpers
Result := add.has ('@') Result := add.has ('@')
end end
invariant
-- invariant_clause: True
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -43,11 +43,8 @@ feature {NONE} -- Initialization
feature -- Status feature -- Status
is_available: BOOLEAN is_available: BOOLEAN
local
f: RAW_FILE
do do
create f.make_with_path (executable_path) Result := (create {RAW_FILE}.make_with_path (executable_path)).exists
Result := f.exists
end end
feature -- Change feature -- Change
@@ -108,7 +105,7 @@ feature -- Basic operation
if attached arguments as l_args then if attached arguments as l_args then
args := l_args.twin args := l_args.twin
else else
if attached {RAW_FILE} new_temporary_file (generator) as f then if attached new_temporary_file (generator) as f then
f.create_read_write f.create_read_write
f.put_string (a_email.message) f.put_string (a_email.message)
f.close f.close
@@ -196,10 +193,8 @@ feature {NONE} -- Implementation
result_creatable: Result.is_creatable result_creatable: Result.is_creatable
end end
invariant
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -4,9 +4,8 @@ note
Note: it is based on EiffelNet {SMTP_PROTOCOL} implementation, and may not be complete. Note: it is based on EiffelNet {SMTP_PROTOCOL} implementation, and may not be complete.
]" ]"
author: "$Author: jfiat $" date: "$Date$"
date: "$Date: 2015-06-30 11:07:17 +0200 (mar., 30 juin 2015) $" revision: "$Revision$"
revision: "$Revision: 97586 $"
class class
NOTIFICATION_SMTP_MAILER NOTIFICATION_SMTP_MAILER
@@ -57,15 +56,12 @@ feature {NONE} -- Initialization
initialize initialize
-- Initialize service. -- Initialize service.
local
l_address_factory: INET_ADDRESS_FACTORY
do do
if attached username as u then if attached username as u then
create smtp_protocol.make (smtp_host, u) create smtp_protocol.make (smtp_host, u)
else else
-- Get local host name needed in creation of SMTP_PROTOCOL. -- Get local host name needed in creation of SMTP_PROTOCOL.
create l_address_factory create smtp_protocol.make (smtp_host, (create {INET_ADDRESS_FACTORY}).create_localhost.host_name)
create smtp_protocol.make (smtp_host, l_address_factory.create_localhost.host_name)
end end
if smtp_port > 0 then if smtp_port > 0 then
smtp_protocol.set_default_port (smtp_port) smtp_protocol.set_default_port (smtp_port)
@@ -98,9 +94,7 @@ feature -- Basic operation
local local
l_email: EMAIL l_email: EMAIL
h: STRING h: STRING
k,v: STRING
i: INTEGER i: INTEGER
hdate: HTTP_DATE
do do
create l_email.make_with_entry (a_email.from_address, addresses_to_header_line_value (a_email.to_addresses)) create l_email.make_with_entry (a_email.from_address, addresses_to_header_line_value (a_email.to_addresses))
if attached a_email.reply_to_address as l_reply_to then if attached a_email.reply_to_address as l_reply_to then
@@ -117,8 +111,7 @@ feature -- Basic operation
l_email.add_header_entry ({EMAIL_CONSTANTS}.H_subject, a_email.subject) l_email.add_header_entry ({EMAIL_CONSTANTS}.H_subject, a_email.subject)
create h.make_empty create h.make_empty
create hdate.make_from_date_time (a_email.date) ;(create {HTTP_DATE}.make_from_date_time (a_email.date)).append_to_rfc1123_string (h)
hdate.append_to_rfc1123_string (h)
l_email.add_header_entry ("Date", h) l_email.add_header_entry ("Date", h)
if attached a_email.additional_header_lines as lst then if attached a_email.additional_header_lines as lst then
@@ -128,9 +121,7 @@ feature -- Basic operation
h := ic.item h := ic.item
i := h.index_of (':', 1) i := h.index_of (':', 1)
if i > 0 then if i > 0 then
k := h.head (i - 1) l_email.add_header_entry (h.head (i - 1), h.substring (i + 1, h.count))
v := h.substring (i + 1, h.count)
l_email.add_header_entry (k, v)
else else
check is_header_line: False end check is_header_line: False end
end end
@@ -181,7 +172,7 @@ feature {NONE} -- Implementation
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -1,7 +1,7 @@
note note
description: "Store emails in specific folder." description: "Store emails in specific folder."
date: "$Date: 2017-03-08 10:34:57 +0100 (mer., 08 mars 2017) $" date: "$Date$"
revision: "$Revision: 99935 $" revision: "$Revision$"
class class
NOTIFICATION_EMAIL_DIRECTORY_STORAGE NOTIFICATION_EMAIL_DIRECTORY_STORAGE
@@ -41,7 +41,7 @@ feature -- Storage
-- Store `a_email'. -- Store `a_email'.
local local
retried: BOOLEAN retried: BOOLEAN
f,w: RAW_FILE w: RAW_FILE
dt: DATE_TIME dt: DATE_TIME
p: PATH p: PATH
fn: STRING fn: STRING
@@ -72,8 +72,7 @@ feature -- Storage
p := p.extended (fn) p := p.extended (fn)
from from
create f.make_with_path (p) w := new_file_opened_for_writing (create {RAW_FILE}.make_with_path (p))
w := new_file_opened_for_writing (f)
until until
w /= Void or i > 100 w /= Void or i > 100
loop loop
@@ -113,14 +112,15 @@ feature -- Storage
local local
retried: BOOLEAN retried: BOOLEAN
do do
if not retried then if
if not f.exists then not retried and then
f.open_write not f.exists
if f.is_open_write then then
Result := f f.open_write
elseif not f.is_closed then if f.is_open_write then
f.close Result := f
end elseif not f.is_closed then
f.close
end end
end end
ensure ensure
@@ -2,8 +2,8 @@ note
description: "[ description: "[
Standalone Web Server connector. Standalone Web Server connector.
]" ]"
date: "$Date: 2016-08-06 13:34:52 +0200 (sam., 06 août 2016) $" date: "$Date$"
revision: "$Revision: 99106 $" revision: "$Revision$"
class class
WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end] WGI_STANDALONE_CONNECTOR [G -> WGI_EXECUTION create make end]
@@ -110,7 +110,7 @@ feature -- Callbacks
on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]]] on_launched_actions: ACTION_SEQUENCE [TUPLE [WGI_STANDALONE_CONNECTOR [WGI_EXECUTION]]]
-- Actions triggered when launched. -- Actions triggered when launched.
-- WARNING: only supported for now with SCOOP concurrency mode. [2016-oct-07] -- WARNING: only supported for now with SCOOP concurrency mode. [2016-10-07]
feature -- Event feature -- Event
@@ -201,7 +201,7 @@ feature -- Server
-- Shutdown web server listening. -- Shutdown web server listening.
do do
if launched then if launched then
-- FIXME jfiat [2015/03/27] : prevent multiple calls (otherwise it hangs) -- FIXME: prevent multiple calls (otherwise it hangs) [2015-03-27]
separate_shutdown_server_on_controller (controller) separate_shutdown_server_on_controller (controller)
end end
end end
@@ -213,7 +213,7 @@ feature -- Events
require require
obs.started -- SCOOP wait condition. obs.started -- SCOOP wait condition.
do do
-- FIXME: this works only with SCOOP concurrency mode. [2016-oct-07] -- FIXME: this works only with SCOOP concurrency mode. [2016-10-07]
if obs.port > 0 then if obs.port > 0 then
on_launched (obs.port) on_launched (obs.port)
end end
@@ -282,9 +282,8 @@ feature {NONE} -- Implementation: element change
cfg.set_is_secure (b) cfg.set_is_secure (b)
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -54,7 +54,7 @@ feature -- Access
force_single_threaded: BOOLEAN assign set_force_single_threaded force_single_threaded: BOOLEAN assign set_force_single_threaded
obsolete obsolete
"Use directly `max_concurrent_connections = 1` [Feb/2017]" "Use directly `max_concurrent_connections = 1` [2017-05-31]"
do do
Result := max_concurrent_connections <= 1 Result := max_concurrent_connections <= 1
end end
@@ -202,7 +202,7 @@ feature -- Element change
-- Force server to handle incoming request in a single thread. -- Force server to handle incoming request in a single thread.
-- i.e set max_concurrent_connections to 1! -- i.e set max_concurrent_connections to 1!
obsolete obsolete
"Use set_max_concurrent_connections (1) [June/2016]" "Use set_max_concurrent_connections (1) [2017-05-31]"
do do
if v then if v then
set_max_concurrent_connections (1) set_max_concurrent_connections (1)
@@ -340,7 +340,7 @@ feature -- SSL Helpers
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -60,6 +60,7 @@ feature -- Execution
req: WGI_REQUEST_FROM_TABLE req: WGI_REQUEST_FROM_TABLE
res: detachable WGI_RESPONSE_STREAM res: detachable WGI_RESPONSE_STREAM
rescued: BOOLEAN rescued: BOOLEAN
utf: UTF_CONVERTER
do do
if not rescued then if not rescued then
a_input.reset a_input.reset
@@ -68,14 +69,14 @@ feature -- Execution
service.execute (req, res) service.execute (req, res)
res.push res.push
else else
if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.exception_trace as l_trace then if attached (create {EXCEPTION_MANAGER}).last_exception as e and then attached e.trace as l_trace then
if res /= Void then if res /= Void then
if not res.status_is_set then if not res.status_is_set then
res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void) res.set_status_code ({HTTP_STATUS_CODE}.internal_server_error, Void)
end end
if res.message_writable then if res.message_writable then
res.put_string ("<pre>") res.put_string ("<pre>")
res.put_string (l_trace) res.put_string (utf.string_32_to_utf_8_string_8 (l_trace))
res.put_string ("</pre>") res.put_string ("</pre>")
end end
res.push res.push
@@ -105,7 +106,7 @@ invariant
fcgi_attached: fcgi /= Void fcgi_attached: fcgi /= Void
note note
copyright: "2011-2013, Eiffel Software and others" copyright: "2011-2017, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -122,7 +122,7 @@ feature {NONE} -- Initialization
then then
secure_settings := [l_secure_prot, opts.option_string_32_value ("secure_certificate", Void), opts.option_string_32_value ("secure_certificate_key", Void)] secure_settings := [l_secure_prot, opts.option_string_32_value ("secure_certificate", Void), opts.option_string_32_value ("secure_certificate_key", Void)]
elseif elseif
-- OBSOLETE: backward compatible with old settings name [oct/2016]. -- OBSOLETE: backward compatible with old settings name [2017-05-31].
opts.option_boolean_value ("ssl_enabled", is_secure) and then opts.option_boolean_value ("ssl_enabled", is_secure) and then
attached opts.option_string_32_value ("ssl_protocol", "tls_1_2") as ssl_prot attached opts.option_string_32_value ("ssl_protocol", "tls_1_2") as ssl_prot
then then
@@ -141,7 +141,7 @@ feature {NONE} -- Initialization
force_single_threaded force_single_threaded
-- Set `single_threaded' to True. -- Set `single_threaded' to True.
obsolete obsolete
"Use set_max_concurrent_connections (1) [Feb/2017]" "Use set_max_concurrent_connections (1) [2017-05-31]"
do do
set_max_concurrent_connections (1) set_max_concurrent_connections (1)
ensure ensure
@@ -238,7 +238,7 @@ feature {NONE} -- Implementation
single_threaded: BOOLEAN single_threaded: BOOLEAN
obsolete obsolete
"Use max_concurrent_connections <= 1 [Feb/2017]" "Use max_concurrent_connections <= 1 [2017-05-31]"
do do
Result := max_concurrent_connections <= 1 Result := max_concurrent_connections <= 1
end end
@@ -277,7 +277,7 @@ feature -- Status report
end end
;note ;note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -20,7 +20,7 @@ feature -- Mapping helper: uri
map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `h' as handler for `a_uri' for request methods `rqst_methods'. -- Map `h' as handler for `a_uri' for request methods `rqst_methods'.
obsolete obsolete
"Use directly `map_uri' [June/2015]" "Use directly `map_uri' [2017-05-31]"
do do
map_uri (a_uri, h, rqst_methods) map_uri (a_uri, h, rqst_methods)
end end
@@ -44,7 +44,7 @@ feature -- Mapping helper: uri agent
map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `proc' as handler for `a_uri' for request methods `rqst_methods'. -- Map `proc' as handler for `a_uri' for request methods `rqst_methods'.
obsolete obsolete
"Use directly `map_uri_agent' [June/2015]" "Use directly `map_uri_agent' [2017-05-31]"
do do
map_uri_agent (a_uri, proc, rqst_methods) map_uri_agent (a_uri, proc, rqst_methods)
end end
@@ -58,7 +58,7 @@ feature -- Mapping helper: uri agent
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -23,7 +23,7 @@ feature -- Mapping helper: uri template
map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_HANDLER; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `h' as handler for `a_tpl' for request methods `rqst_methods'. -- Map `h' as handler for `a_tpl' for request methods `rqst_methods'.
obsolete obsolete
"Use directly `map_uri_template' [June/2015]" "Use directly `map_uri_template' [2017-05-31]"
require require
a_tpl_attached: a_tpl /= Void a_tpl_attached: a_tpl /= Void
h_attached: h /= Void h_attached: h /= Void
@@ -54,7 +54,7 @@ feature -- Mapping helper: uri template agent
map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'. -- Map `proc' as handler for `a_tpl' for request methods `rqst_methods'.
obsolete obsolete
"Use directly `map_uri_template_agent' [June/2015]" "Use directly `map_uri_template_agent' [2017-05-31]"
require require
a_tpl_attached: a_tpl /= Void a_tpl_attached: a_tpl /= Void
proc_attached: proc /= Void proc_attached: proc /= Void
@@ -72,7 +72,7 @@ feature -- Mapping helper: uri template agent
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
+4 -4
View File
@@ -77,7 +77,7 @@ feature -- Mapping
map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_REQUEST_METHODS) map_with_request_methods (a_mapping: WSF_ROUTER_MAPPING; rqst_methods: detachable WSF_REQUEST_METHODS)
-- Map `a_mapping' for request methods `rqst_methods'. -- Map `a_mapping' for request methods `rqst_methods'.
obsolete obsolete
"Use directly `map' [June/2015]" "Use directly `map' [2017-05-31]"
require require
a_mapping_attached: a_mapping /= Void a_mapping_attached: a_mapping /= Void
do do
@@ -135,7 +135,7 @@ feature -- Mapping handler
-- Map the mapping created by factory `f' for resource `a_resource' -- Map the mapping created by factory `f' for resource `a_resource'
-- and only for request methods `rqst_methods' -- and only for request methods `rqst_methods'
obsolete obsolete
"Use directly `handle' [June/2015]" "Use directly `handle' [2017-05-31]"
require require
a_resource_attached: a_resource /= Void a_resource_attached: a_resource /= Void
f_attached: f /= Void f_attached: f /= Void
@@ -166,7 +166,7 @@ feature -- Basic operations
-- And return the associated handler if mapping found and handler executed. -- And return the associated handler if mapping found and handler executed.
--| Violates CQS --| Violates CQS
obsolete obsolete
"Use `dispatch' [2013-mar-21]" "Use `dispatch' [2017-05-31]"
require require
req_attached: req /= Void req_attached: req /= Void
res_attached: res /= Void res_attached: res /= Void
@@ -601,7 +601,7 @@ invariant
pre_execution_actions_attached: pre_execution_actions /= Void pre_execution_actions_attached: pre_execution_actions /= Void
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -24,7 +24,7 @@ feature -- Mapping helper: starts_with
map_starts_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_STARTS_WITH_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS) map_starts_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_STARTS_WITH_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `map_starts_with' [June-2015]" "Use directly `map_starts_with' [2017-05-31]"
require require
a_uri_attached: a_uri /= Void a_uri_attached: a_uri /= Void
h_attached: h /= Void h_attached: h /= Void
@@ -44,7 +44,7 @@ feature -- Mapping helper: starts_with agent
map_starts_with_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [start_path: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_starts_with_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [start_path: READABLE_STRING_8; ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `map_starts_with_agent' [June-2015]" "Use directly `map_starts_with_agent' [2017-05-31]"
require require
a_uri_attached: a_uri /= Void a_uri_attached: a_uri /= Void
proc_attached: proc /= Void proc_attached: proc /= Void
@@ -53,7 +53,7 @@ feature -- Mapping helper: starts_with agent
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -24,7 +24,7 @@ feature -- Mapping helper: uri
map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_with_request_methods (a_uri: READABLE_STRING_8; h: WSF_URI_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `map_uri' [June-2015]" "Use directly `map_uri' [2017-05-31]"
require require
a_uri_attached: a_uri /= Void a_uri_attached: a_uri /= Void
h_attached: h /= Void h_attached: h /= Void
@@ -44,7 +44,7 @@ feature -- Mapping helper: uri agent
map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_agent_with_request_methods (a_uri: READABLE_STRING_8; proc: PROCEDURE [TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `map_uri_agent' [June-2015]" "Use directly `map_uri_agent' [2017-05-31]"
require require
a_uri_attached: a_uri /= Void a_uri_attached: a_uri /= Void
proc_attached: proc /= Void proc_attached: proc /= Void
@@ -53,7 +53,7 @@ feature -- Mapping helper: uri agent
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -24,7 +24,7 @@ feature -- Mapping helper: uri
map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_template_with_request_methods (a_tpl: READABLE_STRING_8; h: WSF_URI_TEMPLATE_CONTEXT_HANDLER [C]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `make_uri_template' [June/2015]" "Use directly `make_uri_template' [2017-05-31]"
require require
a_tpl_attached: a_tpl /= Void a_tpl_attached: a_tpl /= Void
h_attached: h /= Void h_attached: h /= Void
@@ -44,7 +44,7 @@ feature -- Mapping helper: uri agent
map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS) map_uri_template_agent_with_request_methods (a_tpl: READABLE_STRING_8; proc: PROCEDURE [TUPLE [ctx: C; req: WSF_REQUEST; res: WSF_RESPONSE]]; rqst_methods: detachable WSF_REQUEST_METHODS)
obsolete obsolete
"Use directly `make_uri_template_agent' [June/2015]" "Use directly `make_uri_template_agent' [2017-05-31]"
require require
a_tpl_attached: a_tpl /= Void a_tpl_attached: a_tpl /= Void
proc_attached: proc /= Void proc_attached: proc /= Void
@@ -53,7 +53,7 @@ feature -- Mapping helper: uri agent
end end
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
+2 -2
View File
@@ -16,7 +16,7 @@ feature -- Access
uuid: READABLE_STRING_8 uuid: READABLE_STRING_8
obsolete obsolete
"Use `id' which is more general [2014-03]" "Use `id' which is more general [2017-05-31]"
deferred deferred
end end
@@ -116,7 +116,7 @@ feature -- Control
end end
note note
copyright: "2011-2014, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -69,7 +69,7 @@ feature -- Access
frozen string_values: like values frozen string_values: like values
obsolete obsolete
"Use `values' [2012-May-31]" "Use `values' [2017-05-31]"
do do
Result := values Result := values
end end
@@ -81,7 +81,7 @@ feature -- Access
frozen first_string_value: WSF_STRING frozen first_string_value: WSF_STRING
obsolete obsolete
"Use `first_value' [2012-May-31]" "Use `first_value' [2017-05-31]"
do do
Result := first_value Result := first_value
end end
@@ -179,7 +179,7 @@ invariant
string_values_not_empty: values.count >= 1 string_values_not_empty: values.count >= 1
note note
copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -2,8 +2,8 @@ note
description: "[ description: "[
Table which can contain value indexed by a key Table which can contain value indexed by a key
]" ]"
date: "$Date: 2015-11-05 21:52:56 +0100 (jeu., 05 nov. 2015) $" date: "$Date$"
revision: "$Revision: 98081 $" revision: "$Revision$"
class class
WSF_TABLE WSF_TABLE
@@ -86,7 +86,7 @@ feature -- Access
frozen first_key: like first_name frozen first_key: like first_name
obsolete obsolete
"Use first_name [2012-May-31]" "Use first_name [2017-05-31]"
do do
Result := first_name Result := first_name
end end
@@ -94,7 +94,7 @@ feature -- Access
file_name: READABLE_STRING_8 file_name: READABLE_STRING_8
obsolete obsolete
"Use `file_path.name' for unicode support [2013-may]" "Use `file_path.name' for unicode support [2017-05-31]"
do do
Result := file_path.utf_8_name Result := file_path.utf_8_name
end end
@@ -230,7 +230,7 @@ invariant
status_code_set: status_code /= 0 status_code_set: status_code /= 0
note note
copyright: "2011-2013, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -165,7 +165,7 @@ feature -- Access
file_name: READABLE_STRING_8 file_name: READABLE_STRING_8
obsolete obsolete
"Use `file_path.name' for unicode support [2013-may]" "Use `file_path.name' for unicode support [2017-05-31]"
do do
Result := file_path.utf_8_name Result := file_path.utf_8_name
end end
@@ -320,7 +320,7 @@ feature {NONE} -- Implementation: output
end end
note note
copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others"
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
source: "[ source: "[
Eiffel Software Eiffel Software
@@ -184,7 +184,7 @@ feature -- Change
end end
extend_text (t: READABLE_STRING_8) extend_text (t: READABLE_STRING_8)
obsolete "Use extend_html_text (..) 2013-Sept-06" obsolete "Use extend_html_text (..) [2017-05-31]"
do do
extend_html_text (t) extend_html_text (t)
end end
@@ -111,9 +111,9 @@ feature -- Execution
i := l_raw_header.substring_index ("%R%N", 1) i := l_raw_header.substring_index ("%R%N", 1)
if i > 0 then if i > 0 then
-- Skip the first status line. -- Skip the first status line.
create h.make_from_raw_header_data (l_raw_header.substring (i + 2, l_raw_header.count)) create h.make_from_raw_header_data (l_raw_header.substring (i + 2, l_raw_header.count).as_string_8_conversion) -- NOTE: it is string 8 per nature.
else else
create h.make_from_raw_header_data (l_raw_header) create h.make_from_raw_header_data (l_raw_header.as_string_8_conversion)
end end
if attached l_remote_uri.host as l_remote_host then if attached l_remote_uri.host as l_remote_host then
if l_remote_uri.port > 0 then if l_remote_uri.port > 0 then
@@ -0,0 +1,47 @@
note
description: "Summary description for {X_WWW_FORM_URL_ENCODER}."
author: ""
date: "$Date$"
revision: "$Revision$"
class
X_WWW_FORM_URL_ENCODER
inherit
URL_ENCODER
redefine
append_percent_encoded_ascii_character_code_to
end
feature {NONE} -- Implementation: character encoding
append_percent_encoded_ascii_character_code_to (a_code: NATURAL_32; a_result: STRING_GENERAL)
-- <Precursor>
-- Note: space is encoded with '+' for x-www-form-urlencoding.
do
inspect a_code
when
32 -- 32 ' '
then
a_result.append_code (43) -- 43 '+'
when
33, 39, -- ! '
40, 41, 42 -- ( ) *
then
a_result.append_code (a_code) -- Keep slash
else
Precursor (a_code, a_result)
end
end
note
copyright: "Copyright (c) 2011-2017, 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
@@ -50,7 +50,7 @@ feature -- Access
create Result.make (l_title) create Result.make (l_title)
Result.set_description (xml_element_text (x_feed, "subtitle"), "plain") Result.set_description (xml_element_text (x_feed, "subtitle"), "plain")
Result.set_id (xml_element_text (x_feed, "id")) Result.set_id (xml_element_text (x_feed, "id"))
Result.set_updated_date_with_text (xml_element_text (x_feed, "updated")) Result.set_date_with_text (xml_element_text (x_feed, "updated"))
if attached links_from_xml (x_feed, "link") as l_links then if attached links_from_xml (x_feed, "link") as l_links then
across across
l_links as link_ic l_links as link_ic
@@ -68,7 +68,7 @@ feature -- Access
create e.make (e_title) create e.make (e_title)
e.set_description (xml_element_text (x_entry, "summary")) e.set_description (xml_element_text (x_entry, "summary"))
e.set_id (xml_element_text (x_entry, "id")) e.set_id (xml_element_text (x_entry, "id"))
e.set_updated_date_with_text (xml_element_text (x_entry, "updated")) e.set_date_with_text (xml_element_text (x_entry, "updated"))
if attached links_from_xml (x_entry, "link") as l_links then if attached links_from_xml (x_entry, "link") as l_links then
across across
+1 -1
View File
@@ -81,7 +81,7 @@ feature -- Element change
set_updated_date_with_text (a_date_text: detachable READABLE_STRING_32) set_updated_date_with_text (a_date_text: detachable READABLE_STRING_32)
-- Set `date' from date string representation `a_date_text'. -- Set `date' from date string representation `a_date_text'.
obsolete obsolete
"Use set_date_with_text [oct/2015]" "Use set_date_with_text [2017-05-31]"
do do
set_date_with_text (a_date_text) set_date_with_text (a_date_text)
end end
@@ -158,7 +158,7 @@ feature -- Element change
set_updated_date_with_text (a_date_text: detachable READABLE_STRING_32) set_updated_date_with_text (a_date_text: detachable READABLE_STRING_32)
-- Set `date' from date string representation `a_date_text'. -- Set `date' from date string representation `a_date_text'.
obsolete obsolete
"Use set_date_with_text [oct/2015]" "Use set_date_with_text [2017-05-31]"
do do
set_date_with_text (a_date_text) set_date_with_text (a_date_text)
end end
@@ -52,7 +52,7 @@ feature -- Access
if attached xml_element_text (x_channel, "title") as x_title then if attached xml_element_text (x_channel, "title") as x_title then
create Result.make (x_title) create Result.make (x_title)
Result.set_description (xml_element_text (x_channel, "description"), "xhtml") Result.set_description (xml_element_text (x_channel, "description"), "xhtml")
Result.set_updated_date_with_text (xml_element_text (x_channel, "lastBuildDate")) Result.set_date_with_text (xml_element_text (x_channel, "lastBuildDate"))
if attached links_from_xml (x_channel, "link") as l_links then if attached links_from_xml (x_channel, "link") as l_links then
across across
l_links as link_ic l_links as link_ic
@@ -69,7 +69,7 @@ feature -- Access
if attached xml_element_text (x_item, "title") as e_title then if attached xml_element_text (x_item, "title") as e_title then
create e.make (e_title) create e.make (e_title)
e.set_description (xml_element_text (x_item, "description")) e.set_description (xml_element_text (x_item, "description"))
e.set_updated_date_with_text (xml_element_text (x_item, "pubDate")) e.set_date_with_text (xml_element_text (x_item, "pubDate"))
e.set_id (xml_element_text (x_item, "guid")) e.set_id (xml_element_text (x_item, "guid"))
@@ -130,7 +130,7 @@ feature -- Visitor
s.append_string_general ("@") s.append_string_general ("@")
s.append_string (a_link.relation) s.append_string (a_link.relation)
s.append_string (" -> ") s.append_string (" -> ")
s.append_string (a_link.href) s.append_string_general (a_link.href)
append_text (s) append_text (s)
end end