Web form:
- Improvement about web form manipulation (remove a field, set a text value to input fields by name, ...) - Improved web form html generation, especially for select and type checkbox - Updated the date input field interface with a new set_date_value . File response: - "application/force-download" is not a standard MIME content type, so use "application_octet_stream" instead as default. Standalone connector: - Added expected creation procedure for the service launcher. - Added new "secure_port" configuration variable, for SSL standalone service. This way, if `is_secure` is True, the server will use `secure_port` (overrides `port` value). Date: - Improved support for RFC 3339 (a profile of ISO 8601) Removed obsolete and warnings: - removed usage of FILE_NAME - updated code to avoid implicit conversion from STRING_32 to STRING_8 - avoid uneed conversion to STRING_8 (when possible)
This commit is contained in:
@@ -47,21 +47,21 @@ feature {NONE} -- Initialization
|
||||
|
||||
feature -- Access
|
||||
|
||||
name: STRING_8
|
||||
name: READABLE_STRING_8
|
||||
-- name of the cookie.
|
||||
|
||||
value: STRING_8
|
||||
value: READABLE_STRING_8
|
||||
-- value of the cookie.
|
||||
|
||||
expiration: detachable STRING_8
|
||||
expiration: detachable READABLE_STRING_8
|
||||
-- Value of the Expires attribute.
|
||||
|
||||
path: detachable STRING_8
|
||||
path: detachable READABLE_STRING_8
|
||||
-- Value of the Path attribute.
|
||||
-- Path to which the cookie applies.
|
||||
--| The path "/", specify a cookie that apply to all URLs in your site.
|
||||
|
||||
domain: detachable STRING_8
|
||||
domain: detachable READABLE_STRING_8
|
||||
-- Value of the Domain attribute.
|
||||
-- Domain to which the cookies apply.
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ create
|
||||
make_now_utc,
|
||||
make_from_timestamp,
|
||||
make_from_string,
|
||||
make_from_rfc3339_string,
|
||||
make_from_date_time
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
@@ -65,6 +66,18 @@ feature {NONE} -- Initialization
|
||||
date_time := dt
|
||||
elseif attached ansi_c_string_to_date_time (s) as dt then
|
||||
date_time := dt
|
||||
elseif attached rfc3339_string_to_date_time (s) as dt then
|
||||
date_time := dt
|
||||
else
|
||||
has_error := True
|
||||
date_time := epoch
|
||||
end
|
||||
end
|
||||
|
||||
make_from_rfc3339_string (s: READABLE_STRING_GENERAL)
|
||||
do
|
||||
if attached rfc3339_string_to_date_time (s) as dt then
|
||||
date_time := dt
|
||||
else
|
||||
has_error := True
|
||||
date_time := epoch
|
||||
@@ -153,10 +166,13 @@ feature -- Conversion to string
|
||||
append_date_time_to_rfc850_string (date_time, Result)
|
||||
end
|
||||
|
||||
iso8601_string,
|
||||
rfc3339_string: STRING
|
||||
-- String representation following RFC 3339.
|
||||
-- format: [yyyy-mm-ddThh:mi:ssZ]
|
||||
-- https://www.rfc-editor.org/rfc/rfc3339.txt
|
||||
-- note: RFC 3339 is a profile of ISO 8601.
|
||||
-- https://en.wikipedia.org/wiki/ISO_8601
|
||||
do
|
||||
create Result.make (25)
|
||||
append_date_time_to_rfc3339_string (date_time, Result)
|
||||
@@ -241,6 +257,7 @@ feature -- Conversion into string
|
||||
s.append (" GMT") -- SPace + GMT
|
||||
end
|
||||
|
||||
append_date_time_to_iso8601_string,
|
||||
append_date_time_to_rfc3339_string (dt: DATE_TIME; s: STRING_GENERAL)
|
||||
-- Append `dt' as [yyyy-mm-ddThh:mi:ssZ] format to `s'.
|
||||
do
|
||||
@@ -316,7 +333,7 @@ feature -- Helper routines.
|
||||
create fd.make (2, 2)
|
||||
fd.show_trailing_zeros
|
||||
fd.show_zero
|
||||
r64 := t.fine_second
|
||||
r64 := t.second + t.fractional_second * 0.01
|
||||
f := fd.formatted (r64)
|
||||
if f.ends_with_general (".00") then
|
||||
append_2_digits_integer_to (t.second, s) -- ss
|
||||
@@ -670,7 +687,7 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
|
||||
ansi_c_string_to_date_time (s: READABLE_STRING_GENERAL): detachable DATE_TIME
|
||||
-- String representation of `dt' using the RFC 1123
|
||||
-- ANSI C date from `s` string representation using the RFC 1123
|
||||
-- asctime-date = wkday SP date3 SP time SP 4DIGIT
|
||||
-- date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
|
||||
-- ; month day (e.g., Jun 2)
|
||||
@@ -919,10 +936,114 @@ feature {NONE} -- Implementation
|
||||
end
|
||||
end
|
||||
|
||||
rfc3339_string_to_date_time (s: READABLE_STRING_GENERAL): detachable DATE_TIME
|
||||
--| 1985-04-12T23:20:50.52Z
|
||||
--| 1996-12-19T16:39:57-08:00 = 1996-12-20T00:39:57Z
|
||||
--|
|
||||
note
|
||||
EIS: "name=RFC3339", "protocol=URI", "src=https://tools.ietf.org/html/rfc3339"
|
||||
local
|
||||
y,mo,d,h,mi,sec, frac_sec: INTEGER
|
||||
l_off_h, l_off_mi: INTEGER
|
||||
tmp: READABLE_STRING_GENERAL
|
||||
i, j, k, pos: INTEGER
|
||||
err: BOOLEAN
|
||||
do
|
||||
if s /= Void then
|
||||
pos := s.index_of ('T', 1)
|
||||
if pos > 0 then
|
||||
i := 1
|
||||
j := s.index_of ('-', i)
|
||||
if j > i and j < pos then
|
||||
y := s.substring (i, j - 1).to_integer
|
||||
i := j + 1
|
||||
j := s.index_of ('-', i)
|
||||
if j > i and j < pos then
|
||||
mo := s.substring (i, j - 1).to_integer
|
||||
d := s.substring (j + 1, pos - 1).to_integer
|
||||
else
|
||||
err := True
|
||||
end
|
||||
else
|
||||
err := True
|
||||
end
|
||||
i := pos + 1
|
||||
j := s.index_of (':', i)
|
||||
if j > i then
|
||||
h := s.substring (i, j - 1).to_integer
|
||||
i := j + 1
|
||||
j := s.index_of (':', i)
|
||||
if j > i then
|
||||
mi := s.substring (i, j - 1).to_integer
|
||||
from
|
||||
k := j + 1
|
||||
until
|
||||
k > s.count
|
||||
or s[k].is_alpha
|
||||
or s[k] = '+'
|
||||
or s[k] = '-'
|
||||
loop
|
||||
k := k + 1
|
||||
end
|
||||
tmp := s.substring (j + 1, k - 1)
|
||||
j := tmp.index_of ('.', 1)
|
||||
if j > 0 then
|
||||
sec := tmp.head (j - 1).to_integer
|
||||
frac_sec := tmp.substring (j + 1, tmp.count).to_integer
|
||||
else
|
||||
sec := tmp.to_integer
|
||||
end
|
||||
if k <= s.count then
|
||||
if s[k] = '+' then
|
||||
tmp := s.substring (k + 1, s.count)
|
||||
j := tmp.index_of (':', 1)
|
||||
if j > 0 then
|
||||
l_off_h := - tmp.head (j - 1).to_integer
|
||||
l_off_mi := - tmp.substring (j + 1, tmp.count).to_integer
|
||||
else
|
||||
l_off_h := - tmp.to_integer
|
||||
end
|
||||
elseif s[k] = '-' then
|
||||
tmp := s.substring (k + 1, s.count)
|
||||
j := tmp.index_of (':', 1)
|
||||
if j > 0 then
|
||||
l_off_h := + tmp.head (j - 1).to_integer
|
||||
l_off_mi := + tmp.substring (j + 1, tmp.count).to_integer
|
||||
else
|
||||
l_off_h := + tmp.to_integer
|
||||
end
|
||||
elseif s[k] = 'Z' then
|
||||
-- Done
|
||||
else
|
||||
end
|
||||
end
|
||||
else
|
||||
err := True
|
||||
end
|
||||
else
|
||||
err := True
|
||||
end
|
||||
if not err then
|
||||
create Result.make (y, mo, d, h, mi, sec)
|
||||
if frac_sec /= 0 then
|
||||
Result.set_fractionals (frac_sec)
|
||||
Result.time.set_fractionals (frac_sec)
|
||||
end
|
||||
if l_off_h /= 0 then
|
||||
Result.hour_add (l_off_h)
|
||||
end
|
||||
if l_off_mi /= 0 then
|
||||
Result.minute_add (l_off_mi)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
invariant
|
||||
|
||||
note
|
||||
copyright: "2011-2019, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -40,9 +40,9 @@ feature -- Query
|
||||
|
||||
format_id (a_id: READABLE_STRING_GENERAL): INTEGER
|
||||
local
|
||||
s: STRING
|
||||
s: READABLE_STRING_GENERAL
|
||||
do
|
||||
s := a_id.as_string_8.as_lower
|
||||
s := a_id.as_lower
|
||||
if s.same_string (json_name) then
|
||||
Result := json
|
||||
elseif s.same_string (xml_name) then
|
||||
@@ -74,7 +74,7 @@ feature -- Query
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2011, Eiffel Software and others"
|
||||
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -175,7 +175,7 @@ feature -- Header: adding
|
||||
across
|
||||
lines as c
|
||||
loop
|
||||
line := c.item
|
||||
line := c.item.to_string_8
|
||||
if not line.is_empty then
|
||||
if line [line.count] = '%R' then
|
||||
line.remove_tail (1)
|
||||
@@ -223,7 +223,7 @@ feature -- Header: merging
|
||||
across
|
||||
lines as c
|
||||
loop
|
||||
line := c.item
|
||||
line := c.item.to_string_8
|
||||
if not line.is_empty then
|
||||
if line [line.count] = '%R' then
|
||||
line.remove_tail (1)
|
||||
@@ -416,7 +416,7 @@ feature {NONE} -- Implementation: Header queries
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2014, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -106,7 +106,7 @@ feature -- Access
|
||||
loop
|
||||
l_line := ic.item
|
||||
if has_same_header_name (l_line, a_header_name) then
|
||||
res := l_line.substring (n + 2, l_line.count)
|
||||
res := l_line.substring (n + 2, l_line.count).to_string_8
|
||||
res.left_adjust
|
||||
res.right_adjust
|
||||
Result := res
|
||||
@@ -271,25 +271,25 @@ feature -- Content related header
|
||||
put_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8)
|
||||
-- Put content type `a_content_type' with `a_charset' as "charset" parameter.
|
||||
do
|
||||
put_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>)
|
||||
put_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["charset", a_charset]>>)
|
||||
end
|
||||
|
||||
add_content_type_with_charset (a_content_type: READABLE_STRING_8; a_charset: READABLE_STRING_8)
|
||||
-- Same as `put_content_type_with_charset', but allow multiple definition of "Content-Type".
|
||||
do
|
||||
add_content_type_with_parameters (a_content_type, <<["charset", a_charset]>>)
|
||||
add_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["charset", a_charset]>>)
|
||||
end
|
||||
|
||||
put_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8)
|
||||
-- Put content type `a_content_type' with `a_name' as "name" parameter.
|
||||
do
|
||||
put_content_type_with_parameters (a_content_type, <<["name", a_name]>>)
|
||||
put_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["name", a_name]>>)
|
||||
end
|
||||
|
||||
add_content_type_with_name (a_content_type: READABLE_STRING_8; a_name: READABLE_STRING_8)
|
||||
-- same as `put_content_type_with_name', but allow multiple definition of "Content-Type"
|
||||
do
|
||||
add_content_type_with_parameters (a_content_type, <<["name", a_name]>>)
|
||||
add_content_type_with_parameters (a_content_type, {ARRAY [TUPLE [READABLE_STRING_8, READABLE_STRING_8]]} <<["name", a_name]>>)
|
||||
end
|
||||
|
||||
put_content_length (a_length: INTEGER)
|
||||
|
||||
@@ -77,10 +77,10 @@ feature {NONE} -- Initialization
|
||||
-- Look for semi colon as parameter separation
|
||||
p := s.index_of (';', i)
|
||||
if p > 0 then
|
||||
t := s.substring (i, p - 1)
|
||||
t := s.substring (i, p - 1).to_string_8
|
||||
create parameters.make_from_substring (s, p + 1, s.count)
|
||||
else
|
||||
t := s.substring (i, n)
|
||||
t := s.substring (i, n).to_string_8
|
||||
end
|
||||
-- Remove eventual trailing space
|
||||
t.right_adjust
|
||||
@@ -124,7 +124,7 @@ feature -- Access
|
||||
subtype: READABLE_STRING_8
|
||||
-- Sub type
|
||||
|
||||
has_parameter (a_name: READABLE_STRING_8): BOOLEAN
|
||||
has_parameter (a_name: READABLE_STRING_GENERAL): BOOLEAN
|
||||
-- Has Current a parameter?
|
||||
do
|
||||
if attached parameters as plst then
|
||||
@@ -132,7 +132,7 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
|
||||
parameter (a_name: READABLE_STRING_8): detachable READABLE_STRING_8
|
||||
parameter (a_name: READABLE_STRING_GENERAL): detachable READABLE_STRING_8
|
||||
-- Value for eventual parameter named `a_name'.
|
||||
do
|
||||
if attached parameters as plst then
|
||||
@@ -159,7 +159,7 @@ feature -- Conversion
|
||||
loop
|
||||
res.append_character (';')
|
||||
res.append_character (' ')
|
||||
res.append (p.key)
|
||||
res.append ({UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (p.key))
|
||||
res.append_character ('=')
|
||||
res.append_character ('%"')
|
||||
res.append (p.item)
|
||||
@@ -272,13 +272,19 @@ feature -- Status report
|
||||
debug_output: STRING
|
||||
-- String that should be displayed in debugger to represent `Current'.
|
||||
do
|
||||
if type /= Void and subtype /= Void then
|
||||
Result := type + "/" + subtype
|
||||
if attached type as l_type and attached subtype as l_subtype then
|
||||
create Result.make_from_string (l_type)
|
||||
Result.append_character ('/')
|
||||
Result.append (l_subtype)
|
||||
if attached parameters as plst then
|
||||
across
|
||||
plst as p
|
||||
loop
|
||||
Result.append ("; " + p.key + "=" + "%"" + p.item + "%"")
|
||||
Result.append ("; ")
|
||||
Result.append ({UTF_CONVERTER}.utf_32_string_to_utf_8_string_8 (p.key))
|
||||
Result.append ("=%"")
|
||||
Result.append (p.item)
|
||||
Result.append_character ('%"')
|
||||
end
|
||||
end
|
||||
else
|
||||
@@ -290,7 +296,7 @@ invariant
|
||||
type_and_subtype_not_empty: not has_error implies not type.is_empty and not subtype.is_empty
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -20,6 +20,8 @@ feature -- Content type : application
|
||||
-- atom application content-type header
|
||||
|
||||
application_force_download: STRING = "application/force-download"
|
||||
-- Warning: this is not a standard MIME content type.
|
||||
-- Prefer application_octet_stream as default.
|
||||
|
||||
application_javascript: STRING = "application/javascript"
|
||||
-- JavaScript application content-type header
|
||||
|
||||
@@ -9,7 +9,7 @@ class
|
||||
HTTP_PARAMETER_TABLE
|
||||
|
||||
inherit
|
||||
HASH_TABLE [READABLE_STRING_8, STRING_8]
|
||||
STRING_TABLE [READABLE_STRING_8]
|
||||
redefine
|
||||
empty_duplicate
|
||||
end
|
||||
@@ -58,7 +58,8 @@ feature {NONE} -- Implementation
|
||||
-- and put in `out_end_index' the index after found parameter.
|
||||
local
|
||||
n: INTEGER
|
||||
pn,pv: STRING_8
|
||||
pn: READABLE_STRING_8
|
||||
pv: STRING_8
|
||||
i: INTEGER
|
||||
p, q: INTEGER
|
||||
err: BOOLEAN
|
||||
@@ -86,7 +87,7 @@ feature {NONE} -- Implementation
|
||||
if s[p+1] = '%"' then
|
||||
q := s.index_of ('%"', p + 2)
|
||||
if q > 0 then
|
||||
pv := s.substring (p + 2, q - 1)
|
||||
pv := s.substring (p + 2, q - 1).to_string_8
|
||||
from
|
||||
i := q + 1
|
||||
until
|
||||
@@ -108,7 +109,7 @@ feature {NONE} -- Implementation
|
||||
if q = 0 then
|
||||
q := n + 1
|
||||
end
|
||||
pv := s.substring (p + 1, q - 1)
|
||||
pv := s.substring (p + 1, q - 1).to_string_8
|
||||
out_end_index.replace (q + 1)
|
||||
end
|
||||
pv.right_adjust
|
||||
@@ -138,7 +139,7 @@ feature {NONE} -- Duplication
|
||||
end
|
||||
|
||||
note
|
||||
copyright: "2011-2013, Jocelyn Fiat, Eiffel Software and others"
|
||||
copyright: "2011-2020, Jocelyn Fiat, Eiffel Software and others"
|
||||
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
|
||||
source: "[
|
||||
Eiffel Software
|
||||
|
||||
@@ -74,4 +74,29 @@ feature -- Test routines
|
||||
|
||||
end
|
||||
|
||||
test_http_date_rfc3339
|
||||
local
|
||||
s: STRING
|
||||
d: HTTP_DATE
|
||||
dt: DATE_TIME
|
||||
do
|
||||
create dt.make_now_utc
|
||||
create dt.make (1985, 04, 12, 23, 20, 50)
|
||||
dt.set_fractionals (52)
|
||||
dt.time.set_fractionals (52)
|
||||
|
||||
create d.make_from_date_time (dt)
|
||||
s := "1985-04-12T23:20:50.52Z"
|
||||
assert ("RFC 3339 to string", d.rfc3339_string.same_string (s))
|
||||
|
||||
create d.make_from_rfc3339_string (s)
|
||||
assert ("RFC 3339 from string", not d.has_error and then d.date_time.is_equal (dt))
|
||||
|
||||
create d.make_from_rfc3339_string ("1996-12-19T16:39:57-08:00")
|
||||
assert ("-8hours", d.rfc3339_string.same_string ("1996-12-20T00:39:57Z"))
|
||||
|
||||
create d.make_from_rfc3339_string ("1937-01-01T12:00:27.87+00:20")
|
||||
assert ("-8hours", d.rfc3339_string.same_string ("1937-01-01T11:40:27.87Z"))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<concurrency support="none" use="none"/>
|
||||
</capability>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time.ecf"/>
|
||||
<library name="http" location="..\http.ecf" readonly="false">
|
||||
<option>
|
||||
<assertions precondition="true" postcondition="true" check="true"/>
|
||||
|
||||
Reference in New Issue
Block a user