Skip to content

Commit 44b1ccb

Browse files
committed
Merge branch 'jvelilla-ewf_cookie'
2 parents 5f4ab50 + 3026163 commit 44b1ccb

File tree

7 files changed

+888
-1
lines changed

7 files changed

+888
-1
lines changed
Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
note
2+
description: "[
3+
This class represents the value of a HTTP cookie, transferred in a request.
4+
The class has features to build an HTTP cookie.
5+
6+
Following a newer RFC standard for Cookies http://tools.ietf.org/html/rfc6265
7+
8+
Domain
9+
* WARNING: Some existing user agents treat an absent Domain attribute as if the Domain attribute were present and contained the current host name.
10+
* For example, if example.com returns a Set-Cookie header without a Domain attribute, these user agents will erroneously send the cookie to www.example.com as well.
11+
12+
Max-Age, Expires
13+
* If a cookie has both the Max-Age and the Expires attribute, the Max-Age attribute has precedence and controls the expiration date of the cookie.
14+
* If a cookie has neither the Max-Age nor the Expires attribute, the user agent will retain the cookie until "the current session is over" (as defined by the user agent).
15+
* You will need to call the feature
16+
17+
HttpOnly, Secure
18+
* Note that the HttpOnly attribute is independent of the Secure attribute: a cookie can have both the HttpOnly and the Secure attribute.
19+
20+
]"
21+
date: "$Date$"
22+
revision: "$Revision$"
23+
EIS: "name=HTTP Cookie specification", "src=http://tools.ietf.org/html/rfc6265", "protocol=uri"
24+
class
25+
HTTP_COOKIE
26+
27+
create
28+
make
29+
30+
feature {NONE} -- Initialization
31+
32+
make (a_name: READABLE_STRING_8; a_value: READABLE_STRING_8)
33+
-- Create an object instance of cookie with name `a_name' and value `a_value'.
34+
require
35+
a_name_not_blank: a_name /= Void and then not a_name.is_whitespace
36+
a_name_has_valid_characters: a_name /= Void and then has_valid_characters (a_name)
37+
a_value_has_valid_characters: a_value /= Void and then has_valid_characters (a_value)
38+
do
39+
set_name (a_name)
40+
set_value(a_value)
41+
set_max_age (-1)
42+
ensure
43+
name_set: name = a_name
44+
value_set: value = a_value
45+
max_age_set: max_age < 0
46+
end
47+
48+
feature -- Access
49+
50+
name: STRING_8
51+
-- name of the cookie.
52+
53+
value: STRING_8
54+
-- value of the cookie.
55+
56+
expiration: detachable STRING_8
57+
-- Value of the Expires attribute.
58+
59+
path: detachable STRING_8
60+
-- Value of the Path attribute.
61+
-- Path to which the cookie applies.
62+
--| The path "/", specify a cookie that apply to all URLs in your site.
63+
64+
domain: detachable STRING_8
65+
-- Value of the Domain attribute.
66+
-- Domain to which the cookies apply.
67+
68+
secure: BOOLEAN
69+
-- Value of the Secure attribute.
70+
-- By default False.
71+
--| Indicate if the cookie should only be sent over secured(encrypted connections, for example SSL).
72+
73+
http_only: BOOLEAN
74+
-- Value of the http_only attribute.
75+
-- By default false.
76+
--| Limits the scope of the cookie to HTTP requests.
77+
78+
max_age: INTEGER
79+
-- Value of the Max-Age attribute.
80+
--| How much time in seconds should elapsed before the cookie expires.
81+
--| By default max_age < 0 indicate a cookie will last only for the current user-agent (Browser, etc) session.
82+
--| A value of 0 instructs the user-agent to delete the cookie.
83+
84+
has_valid_characters (a_name: READABLE_STRING_8):BOOLEAN
85+
-- Has `a_name' valid characters for cookies?
86+
local
87+
l_iterator: STRING_ITERATION_CURSOR
88+
l_found: BOOLEAN
89+
do
90+
create l_iterator.make (a_name)
91+
Result := True
92+
across
93+
l_iterator as ic
94+
until
95+
l_found
96+
loop
97+
if not is_valid_character (ic.item.natural_32_code) then
98+
Result := False
99+
l_found := True
100+
end
101+
end
102+
end
103+
104+
include_max_age: BOOLEAN
105+
-- Does the Set-Cookie header include Max-Age attribute?
106+
--|By default will include both.
107+
108+
include_expires: BOOLEAN
109+
-- Does the Set-Cookie header include Expires attribute?
110+
--|By default will include both.
111+
112+
113+
is_valid_rfc1123_date (a_string: READABLE_STRING_8): BOOLEAN
114+
-- Is the date represented by `a_string' a valid rfc1123 date?
115+
local
116+
d: HTTP_DATE
117+
do
118+
create d.make_from_string (a_string)
119+
Result := not d.has_error and then d.rfc1123_string.same_string (a_string)
120+
end
121+
122+
feature -- Change Element
123+
124+
set_name (a_name: READABLE_STRING_8)
125+
-- Set `name' with `a_name'.
126+
require
127+
a_name_not_blank: a_name /= Void and then not a_name.is_whitespace
128+
a_name_has_valid_characters: a_name /= Void and then has_valid_characters (a_name)
129+
do
130+
name := a_name
131+
ensure
132+
name_set: name = a_name
133+
end
134+
135+
set_value (a_value: READABLE_STRING_8)
136+
-- Set `value' with `a_value'.
137+
require
138+
a_value_has_valid_characters: a_value /= Void and then has_valid_characters (a_value)
139+
do
140+
value := a_value
141+
ensure
142+
value_set: value = a_value
143+
end
144+
145+
set_expiration (a_date: READABLE_STRING_8)
146+
-- Set `expiration' with `a_date'
147+
require
148+
rfc1133_date: a_date /= Void and then is_valid_rfc1123_date (a_date)
149+
do
150+
expiration := a_date
151+
ensure
152+
expiration_set: attached expiration as l_expiration and then l_expiration.same_string (a_date)
153+
end
154+
155+
set_expiration_date (a_date: DATE_TIME)
156+
-- Set `expiration' with `a_date'
157+
do
158+
set_expiration (date_to_rfc1123_http_date_format (a_date))
159+
ensure
160+
expiration_set: attached expiration as l_expiration and then l_expiration.same_string (date_to_rfc1123_http_date_format (a_date))
161+
end
162+
163+
set_path (a_path: READABLE_STRING_8)
164+
-- Set `path' with `a_path'
165+
do
166+
path := a_path
167+
ensure
168+
path_set: path = a_path
169+
end
170+
171+
set_domain (a_domain: READABLE_STRING_8)
172+
-- Set `domain' with `a_domain'
173+
-- Note: you should avoid using "localhost" as `domain' for local cookies
174+
-- since they are not always handled by browser (for instance Chrome)
175+
require
176+
domain_without_port_info: a_domain /= Void implies not a_domain.has (':')
177+
do
178+
domain := a_domain
179+
ensure
180+
domain_set: domain = a_domain
181+
end
182+
183+
set_secure (a_secure: BOOLEAN)
184+
-- Set `secure' with `a_secure'
185+
do
186+
secure := a_secure
187+
ensure
188+
secure_set: secure = a_secure
189+
end
190+
191+
set_http_only (a_http_only: BOOLEAN)
192+
-- Set `http_only' with `a_http_only'
193+
do
194+
http_only := a_http_only
195+
ensure
196+
http_only_set: http_only = a_http_only
197+
end
198+
199+
set_max_age (a_max_age: INTEGER)
200+
-- Set `max_age' with `a_max_age'
201+
do
202+
max_age := a_max_age
203+
ensure
204+
max_age_set: max_age = a_max_age
205+
end
206+
207+
208+
mark_max_age
209+
-- Set `include_max_age' to True.
210+
-- Set `include_expires' to False.
211+
-- Set-Cookie will include only Max-Age attribute and not Expires.
212+
do
213+
include_max_age := True
214+
include_expires := False
215+
ensure
216+
max_age_true: include_max_age
217+
expire_false: not include_expires
218+
end
219+
220+
mark_expires
221+
-- Set `include_expires' to True.
222+
-- Set `include_max_age' to False
223+
-- Set-Cookie will include only Expires attribute and not Max_Age.
224+
do
225+
include_expires := True
226+
include_max_age := False
227+
ensure
228+
expires_true: include_expires
229+
max_age_false: not include_max_age
230+
end
231+
232+
set_default_expires_max_age
233+
-- Set `include_expires' to False.
234+
-- Set `include_max_age' to False
235+
-- Set-Cookie will include both Max-Age, Expires attributes.
236+
do
237+
include_expires := False
238+
include_max_age := False
239+
ensure
240+
expires_false: not include_expires
241+
max_age_false: not include_max_age
242+
end
243+
244+
feature {NONE} -- Date Utils
245+
246+
date_to_rfc1123_http_date_format (dt: DATE_TIME): STRING_8
247+
-- String representation of `dt' using the RFC 1123
248+
local
249+
d: HTTP_DATE
250+
do
251+
create d.make_from_date_time (dt)
252+
Result := d.string
253+
end
254+
255+
feature -- Output
256+
257+
header_line: STRING
258+
-- String representation of Set-Cookie header line of Current.
259+
local
260+
s: STRING
261+
do
262+
s := {HTTP_HEADER_NAMES}.header_set_cookie + colon_space + name + "=" + value
263+
if
264+
attached domain as l_domain and then not l_domain.same_string ("localhost")
265+
then
266+
s.append ("; Domain=")
267+
s.append (l_domain)
268+
end
269+
if attached path as l_path then
270+
s.append ("; Path=")
271+
s.append (l_path)
272+
end
273+
-- Expire
274+
if include_expires then
275+
if attached expiration as l_expires then
276+
s.append ("; Expires=")
277+
s.append (l_expires)
278+
end
279+
-- Max-Age
280+
elseif include_max_age then
281+
s.append ("; Max-Age=")
282+
s.append_integer (max_age)
283+
else
284+
-- Default
285+
check
286+
-- By default the attributes include_expires and include_max_age are False.
287+
-- Meaning that Expires and Max-Age headers are included in the response.
288+
default: (not include_expires) and (not include_max_age)
289+
end
290+
if attached expiration as l_expires then
291+
s.append ("; Expires=")
292+
s.append (l_expires)
293+
end
294+
295+
s.append ("; Max-Age=")
296+
s.append_integer (max_age)
297+
end
298+
299+
if secure then
300+
s.append ("; Secure")
301+
end
302+
if http_only then
303+
s.append ("; HttpOnly")
304+
end
305+
Result := s
306+
end
307+
308+
feature {NONE} -- Constants
309+
310+
311+
colon_space: IMMUTABLE_STRING_8
312+
once
313+
create Result.make_from_string (": ")
314+
end
315+
316+
317+
is_valid_character (c: NATURAL_32): BOOLEAN
318+
-- RFC6265 that specifies that the following is valid for characters in cookies.
319+
-- The following character ranges are valid:http://tools.ietf.org/html/rfc6265#section-4.1.1
320+
-- %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
321+
-- 0x21: !
322+
-- 0x23-2B: #$%&'()*+
323+
-- 0x2D-3A: -./0123456789:
324+
-- 0x3C-5B: <=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[
325+
-- 0x5D-7E: ]^_`abcdefghijklmnopqrstuvwxyz{|}~
326+
note
327+
EIS: "name=valid-characters", "src=http://tools.ietf.org/html/rfc6265#section-4.1.1", "protocol=uri"
328+
do
329+
Result := True
330+
inspect c
331+
when 0x21 then
332+
when 0x23 .. 0x2B then
333+
when 0x2D .. 0x3A then
334+
when 0x3C .. 0x5B then
335+
when 0x5D .. 0x7E then
336+
else
337+
Result := False
338+
end
339+
end
340+
341+
note
342+
copyright: "2011-2015, Jocelyn Fiat, Eiffel Software and others"
343+
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
344+
source: "[
345+
Eiffel Software
346+
5949 Hollister Ave., Goleta, CA 93117 USA
347+
Telephone 805-685-1006, Fax 805-685-6869
348+
Website http://www.eiffel.com
349+
Customer support http://support.eiffel.com
350+
]"
351+
end

0 commit comments

Comments
 (0)