dwaite-cookiejar 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cookiejar.rb CHANGED
@@ -1,3 +1,2 @@
1
- require 'cookiejar/cookie_common'
2
1
  require 'cookiejar/cookie'
3
2
  require 'cookiejar/jar'
@@ -1,6 +1,6 @@
1
1
  require 'time'
2
2
  require 'uri'
3
- require 'cookiejar/cookie_common'
3
+ require 'cookiejar/cookie_validation'
4
4
 
5
5
  module CookieJar
6
6
 
@@ -10,28 +10,6 @@ module CookieJar
10
10
  # Specifically, the 'domain' and 'path' values may be set to defaults
11
11
  # based on the requested resource that resulted in the cookie being set.
12
12
  class Cookie
13
- module PATTERN
14
- include URI::REGEXP::PATTERN
15
-
16
- TOKEN = '[^(),\/<>@;:\\\"\[\]?={}\s]*'
17
- VALUE1 = "([^;]*)"
18
- IPADDR = "#{IPV4ADDR}|#{IPV6ADDR}"
19
- BASE_HOSTNAME = "(?:#{DOMLABEL}\\.)(?:((?:(?:#{DOMLABEL}\\.)+(?:#{TOPLABEL}\\.?))|local))"
20
-
21
- # QUOTED_PAIR = "\\\\[\\x00-\\x7F]"
22
- # LWS = "\\r\\n(?:[ \\t]+)"
23
- # TEXT="[\\t\\x20-\\x7E\\x80-\\xFF]|(?:#{LWS})"
24
- # QDTEXT="[\\t\\x20-\\x21\\x23-\\x7E\\x80-\\xFF]|(?:#{LWS})"
25
- # QUOTED_TEXT = "\\\"((?:#{QDTEXT}|#{QUOTED_PAIR})*)\\\""
26
- # VALUE2 = "(#{TOKEN})|#{QUOTED_TEXT}"
27
-
28
- end
29
- BASE_HOSTNAME = /#{PATTERN::BASE_HOSTNAME}/
30
- BASE_PATH = /\A((?:[^\/?#]*\/)*)/
31
- IPADDR = /\A#{PATTERN::IPADDR}\Z/
32
- # HDN = /\A#{PATTERN::HOSTNAME}\Z/
33
- # TOKEN = /\A#{PATTERN::TOKEN}\Z/
34
- # TWO_DOT_DOMAINS = /\A\.(com|edu|net|mil|gov|int|org)\Z/
35
13
 
36
14
  # The mandatory name and value of the cookie
37
15
  attr_reader :name, :value
@@ -74,111 +52,29 @@ module CookieJar
74
52
  end
75
53
  end
76
54
 
77
- def expired?
55
+ def is_expired?
78
56
  expires_at != nil && Time.now > expires_at
79
57
  end
80
-
58
+
59
+ def is_session?
60
+ @expiry == nil
61
+ end
62
+
81
63
  # Create a cookie based on an absolute URI and the string value of a
82
64
  # 'Set-Cookie' header.
83
65
  def self.from_set_cookie request_uri, set_cookie_value
84
- args = { }
85
- params=set_cookie_value.split /;\s*/
86
- params.each do |param|
87
- result = PARAM1.match param
88
- if !result
89
- raise InvalidCookieError.new "Invalid cookie parameter in cookie '#{set_cookie_value}'"
90
- end
91
- key = result[1].downcase.to_sym
92
- keyvalue = result[2]
93
- case key
94
- when :expires
95
- args[:expires_at] = Time.parse keyvalue
96
- when :domain
97
- args[:domain] = keyvalue
98
- when :path
99
- args[:path] = keyvalue
100
- when :secure
101
- args[:secure] = true
102
- when :httponly
103
- args[:http_only] = true
104
- else
105
- args[:name] = result[1]
106
- args[:value] = keyvalue
107
- end
108
- end
109
- args[:domain] = determine_cookie_domain request_uri, args[:domain]
110
- args[:path] = determine_cookie_path request_uri, args[:path]
111
- args[:version] = 0
66
+ args = CookieJar::CookieValidation.parse_set_cookie set_cookie_value
67
+ args[:domain] = CookieJar::CookieValidation.determine_cookie_domain request_uri, args[:domain]
68
+ args[:path] = CookieJar::CookieValidation.determine_cookie_path request_uri, args[:path]
112
69
  cookie = Cookie.new args
113
- validate_cookie request_uri, cookie
70
+ CookieJar::CookieValidation.validate_cookie request_uri, cookie
114
71
  cookie
115
72
  end
116
73
 
117
74
  def to_s
118
- %^"#{name}=#{value}#{if domain then "; domain=#{domain}" end}#{if expiry then "; expiry=#{expiry}" end}#{if path then "; path=#{path}" end}#{if secure then "; secure" end }#{if http_only then "; HTTPOnly" end}^
75
+ "#{name}=#{value}"
119
76
  end
120
77
 
121
- # Check whether a cookie meets all of the rules to be created, based on
122
- # its internal settings and the URI it came from.
123
- #
124
- # returns true on success, but will raise an InvalidCookieError on failure
125
- # with an appropriate error message
126
- def self.validate_cookie request_uri, cookie
127
- uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
128
-
129
- request_host = effective_host uri.host
130
- request_path = uri.path
131
- request_secure = (uri.scheme == 'https')
132
- cookie_host = cookie.domain
133
- cookie_path = cookie.path
134
-
135
- errors = []
136
-
137
- # From RFC 2965, Section 3.3.2 Rejecting Cookies
138
-
139
- # A user agent rejects (SHALL NOT store its information) if the
140
- # Version attribute is missing. Note that the legacy Set-Cookie
141
- # directive will result in an implicit version 0.
142
- unless cookie.version
143
- errors << "Version missing"
144
- end
145
-
146
- # The value for the Path attribute is not a prefix of the request-URI
147
- unless request_path.start_with? cookie_path
148
- errors << "Path is not a prefix of the request uri path"
149
- end
150
-
151
- unless cookie_host =~ IPADDR || #is an IPv4 or IPv6 address
152
- cookie_host =~ /.\../ || #contains an embedded dot
153
- cookie_host == '.local' #is the domain cookie for local addresses
154
- errors << "Domain format is illegal"
155
- end
156
-
157
- # The effective host name that derives from the request-host does
158
- # not domain-match the Domain attribute.
159
- #
160
- # The request-host is a HDN (not IP address) and has the form HD,
161
- # where D is the value of the Domain attribute, and H is a string
162
- # that contains one or more dots.
163
- effective_host = effective_host uri
164
- unless domains_match effective_host, cookie_host
165
- errors << "Domain is inappropriate based on request URI hostname"
166
- end
167
-
168
- # The Port attribute has a "port-list", and the request-port was
169
- # not in the list.
170
- unless cookie.ports.nil? || cookie.ports.length != 0
171
- unless cookie.ports.find_index uri.port
172
- errors << "Ports list does not contain request URI port"
173
- end
174
- end
175
-
176
- raise InvalidCookieError.new errors unless errors.empty?
177
-
178
- # Note: 'secure' is not explicitly defined as an SSL channel, and no
179
- # test is defined around validity and the 'secure' attribute
180
- true
181
- end
182
78
  # Return true if (given a URI, a cookie object and other options) a cookie
183
79
  # should be sent to a host. Note that this currently ignores domain.
184
80
  #
@@ -190,127 +86,58 @@ module CookieJar
190
86
  path_match = uri.path.start_with? @path
191
87
  secure_match = !(@secure && uri.scheme == 'http')
192
88
  script_match = !(script && @http_only)
193
- expiry_match = !expired?
89
+ expiry_match = !is_expired?
194
90
  path_match && secure_match && script_match && expiry_match
195
91
  end
196
92
 
197
- # Compute the base of a path.
198
- def self.cookie_base_path path
199
- path = path.is_a?(URI) ? path.path : path
200
- BASE_PATH.match(path)[1]
201
- end
202
-
203
- # Processes cookie path data using the following rules:
204
- # Paths are separated by '/' characters, and accepted values are truncated
205
- # to the last '/' character. If no path is specified in the cookie, a path
206
- # value will be taken from the request URI which was used for the site.
207
- #
208
- # Note that this will not attempt to detect a mismatch of the request uri domain
209
- # and explicitly specified cookie path
210
- def self.determine_cookie_path request_uri, cookie_path
211
- uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
212
- cookie_path = cookie_path.is_a?(Cookie) ? cookie_path.path : cookie_path
213
-
214
- if cookie_path == nil || cookie_path.empty?
215
- cookie_path = cookie_base_path uri.path
216
- end
217
- cookie_path
218
- end
219
-
220
- # Given a URI, compute the relevant search domains for pre-existing
221
- # cookies. This includes all the valid dotted forms for a named or IP
222
- # domains.
223
- def self.compute_search_domains request_uri
224
- uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
225
- host = effective_host uri
226
- result = [host]
227
- if host !~ IPADDR
228
- result << ".#{host}"
93
+ def to_json *a
94
+ result = {
95
+ :json_class => self.class.name,
96
+ :name => @name,
97
+ :value => @value,
98
+ :domain => @domain,
99
+ :path => @path,
100
+ :created_at => @created_at
101
+ }
102
+ {
103
+ :expiry => @expiry,
104
+ :secure => (true if @secure),
105
+ :http_only => (true if @http_only),
106
+ :version => (@version if version != 0),
107
+ :comment => @comment,
108
+ :comment_url => @comment_url,
109
+ :discard => (true if @discard),
110
+ :ports => @ports
111
+ }.each do |name, value|
112
+ result[name] = value if value
229
113
  end
230
- base = hostname_reach host
231
- if base
232
- result << ".#{base}"
233
- end
234
- result
114
+ result.to_json(*a)
235
115
  end
236
-
237
- # Processes cookie domain data using the following rules:
238
- # Domains strings of the form .foo.com match 'foo.com' and all immediate
239
- # subdomains of 'foo.com'. Domain strings specified of the form 'foo.com' are
240
- # modified to '.foo.com', and as such will still apply to subdomains.
241
- #
242
- # Cookies without an explicit domain will have their domain value taken directly
243
- # from the URL, and will _NOT_ have any leading dot applied. For example, a request
244
- # to http://foo.com/ will cause an entry for 'foo.com' to be created - which applies
245
- # to foo.com but no subdomain.
246
- #
247
- # Note that this will not attempt to detect a mismatch of the request uri domain
248
- # and explicitly specified cookie domain
249
- def self.determine_cookie_domain request_uri, cookie_domain
250
- uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
251
- domain = cookie_domain.is_a?(Cookie) ? cookie_domain.domain : cookie_domain
252
-
253
- if domain == nil || domain.empty?
254
- domain = effective_host uri.host
255
- else
256
- domain = domain.downcase
257
- if domain =~ IPADDR || domain.start_with?('.')
258
- domain
259
- else
260
- ".#{domain}"
261
- end
116
+ def self.json_create o
117
+ params = o.inject({}) do |hash, (key, value)|
118
+ hash[key.to_sym] = value
119
+ hash
262
120
  end
263
- end
264
- # Compute the effective host (RFC 2965, section 1)
265
- # [host] a string or URI.
266
- #
267
- # Has the added additional logic of searching for interior dots specifically, and
268
- # matches colons to prevent .local being suffixed on IPv6 addresses
269
- def self.effective_host host
270
- hostname = host.is_a?(URI) ? host.host : host
271
- hostname = hostname.downcase
272
-
273
- if /.[\.:]./.match(hostname) || hostname == '.local'
274
- hostname
121
+ params[:version] ||= 0
122
+ params[:created_at] = Time.parse params[:created_at]
123
+ if params[:expiry].is_a? String
124
+ params[:expires_at] = Time.parse params[:expiry]
275
125
  else
276
- hostname + '.local'
126
+ params[:max_age] = params[:expiry]
277
127
  end
278
- end
279
- # Compare a base domain against the base domain to see if they match, or
280
- # if the base domain is reachable
281
- def self.domains_match tested_domain,base_domain
282
- return true if (tested_domain == base_domain || ".#{tested_domain}" == base_domain)
283
- lhs = effective_host tested_domain
284
- rhs = effective_host base_domain
285
- lhs == rhs || ".#{lhs}" == rhs || hostname_reach(lhs) == rhs || ".#{hostname_reach lhs}" == rhs
128
+ params.delete :expiry
129
+
130
+ self.new params
286
131
  end
287
- # Compute the reach of a hostname (RFC 2965, section 1)
288
- # Determines the next highest superdomain, or nil if none valid
289
- def self.hostname_reach hostname
290
- host = hostname.is_a?(URI) ? hostname.host : hostname
291
- host = host.downcase
292
- match = BASE_HOSTNAME.match host
293
- if match
294
- match[1]
295
- end
132
+ def self.compute_search_domains request_uri
133
+ CookieValidation.compute_search_domains request_uri
296
134
  end
297
135
  protected
298
- PARAM1 = /\A(#{PATTERN::TOKEN})(?:=#{PATTERN::VALUE1})?\Z/
299
- # PARAM2 = /\A(#{PATTERN::TOKEN})(?:=#{PATTERN::VALUE2})?\Z/
300
-
301
- def initialize *params
302
- case params.length
303
- when 1
304
- args = params[0]
305
- when 2
306
- args = {:name => params[0], :value => params[1], :version => 0}
307
- else
308
- raise ArgumentError.new "wrong number of arguments (expected 1 or 2)"
309
- end
136
+ def initialize args
310
137
 
311
- @created_at = Time.now
138
+ @created_at = args[:created_at] || Time.now
312
139
  @domain = args[:domain]
313
- @expiry = args[:max_age] || args[:expires_at] || nil
140
+ @expiry = args[:max_age] || args[:expires_at]
314
141
  @path = args[:path]
315
142
  @secure = args[:secure] || false
316
143
  @http_only = args[:http_only] || false
@@ -327,4 +154,4 @@ module CookieJar
327
154
  end
328
155
  end
329
156
  end
330
- end
157
+ end
@@ -0,0 +1,271 @@
1
+
2
+ module CookieJar
3
+ # Represents all cookie validation errors
4
+ class InvalidCookieError < StandardError
5
+ attr_reader :messages
6
+ def initialize message
7
+ if message.is_a? Array
8
+ @messages = message
9
+ message = message.join ', '
10
+ end
11
+ super(message)
12
+ end
13
+ end
14
+
15
+ # Contains logic to parse and validate cookie headers
16
+ module CookieValidation
17
+ module PATTERN
18
+ include URI::REGEXP::PATTERN
19
+
20
+ TOKEN = '[^(),\/<>@;:\\\"\[\]?={}\s]*'
21
+ VALUE1 = "([^;]*)"
22
+ IPADDR = "#{IPV4ADDR}|#{IPV6ADDR}"
23
+ BASE_HOSTNAME = "(?:#{DOMLABEL}\\.)(?:((?:(?:#{DOMLABEL}\\.)+(?:#{TOPLABEL}\\.?))|local))"
24
+
25
+ # QUOTED_PAIR = "\\\\[\\x00-\\x7F]"
26
+ # LWS = "\\r\\n(?:[ \\t]+)"
27
+ # TEXT="[\\t\\x20-\\x7E\\x80-\\xFF]|(?:#{LWS})"
28
+ # QDTEXT="[\\t\\x20-\\x21\\x23-\\x7E\\x80-\\xFF]|(?:#{LWS})"
29
+ # QUOTED_TEXT = "\\\"((?:#{QDTEXT}|#{QUOTED_PAIR})*)\\\""
30
+ # VALUE2 = "(#{TOKEN})|#{QUOTED_TEXT}"
31
+
32
+ end
33
+ BASE_HOSTNAME = /#{PATTERN::BASE_HOSTNAME}/
34
+ BASE_PATH = /\A((?:[^\/?#]*\/)*)/
35
+ IPADDR = /\A#{PATTERN::IPADDR}\Z/
36
+ HDN = /\A#{PATTERN::HOSTNAME}\Z/
37
+ TOKEN = /\A#{PATTERN::TOKEN}\Z/
38
+ PARAM1 = /\A(#{PATTERN::TOKEN})(?:=#{PATTERN::VALUE1})?\Z/
39
+ # PARAM2 = /\A(#{PATTERN::TOKEN})(?:=#{PATTERN::VALUE2})?\Z/
40
+
41
+ # TWO_DOT_DOMAINS = /\A\.(com|edu|net|mil|gov|int|org)\Z/
42
+
43
+ # Converts the input object to a URI (if not already a URI)
44
+ def self.to_uri request_uri
45
+ (request_uri.is_a? URI)? request_uri : (URI.parse request_uri)
46
+ end
47
+
48
+ # Converts an input cookie or uri to a string representing the path.
49
+ # Assume strings are already paths
50
+ def self.to_path uri_or_path
51
+ if (uri_or_path.is_a? URI) || (uri_or_path.is_a? Cookie)
52
+ uri_or_path.path
53
+ else
54
+ uri_or_path
55
+ end
56
+ end
57
+
58
+ # Converts an input cookie or uri to a string representing the domain.
59
+ # Assume strings are already domains
60
+ def self.to_domain uri_or_domain
61
+ if uri_or_domain.is_a? URI
62
+ uri_or_domain.host
63
+ elsif uri_or_domain.is_a? Cookie
64
+ uri_or_domain.domain
65
+ else
66
+ uri_or_domain
67
+ end
68
+ end
69
+
70
+ # Compare a tested domain against the base domain to see if they match, or
71
+ # if the base domain is reachable.
72
+ #
73
+ # returns the effective_host on success, nil on failure
74
+ def self.domains_match tested_domain, base_domain
75
+ base = effective_host base_domain
76
+ search_domains = compute_search_domains_for_host base
77
+ result = search_domains.find do |domain|
78
+ domain == tested_domain
79
+ end
80
+ end
81
+
82
+ # Compute the reach of a hostname (RFC 2965, section 1)
83
+ # Determines the next highest superdomain, or nil if none valid
84
+ def self.hostname_reach hostname
85
+ host = to_domain hostname
86
+ host = host.downcase
87
+ match = BASE_HOSTNAME.match host
88
+ if match
89
+ match[1]
90
+ end
91
+ end
92
+
93
+ # Compute the base of a path.
94
+ def self.cookie_base_path path
95
+ BASE_PATH.match(to_path path)[1]
96
+ end
97
+
98
+ # Processes cookie path data using the following rules:
99
+ # Paths are separated by '/' characters, and accepted values are truncated
100
+ # to the last '/' character. If no path is specified in the cookie, a path
101
+ # value will be taken from the request URI which was used for the site.
102
+ #
103
+ # Note that this will not attempt to detect a mismatch of the request uri domain
104
+ # and explicitly specified cookie path
105
+ def self.determine_cookie_path request_uri, cookie_path
106
+ uri = to_uri request_uri
107
+ cookie_path = to_path cookie_path
108
+
109
+ if cookie_path == nil || cookie_path.empty?
110
+ cookie_path = cookie_base_path uri.path
111
+ end
112
+ cookie_path
113
+ end
114
+
115
+ # Given a URI, compute the relevant search domains for pre-existing
116
+ # cookies. This includes all the valid dotted forms for a named or IP
117
+ # domains.
118
+ def self.compute_search_domains request_uri
119
+ uri = to_uri request_uri
120
+ host = uri.host
121
+ compute_search_domains_for_host host
122
+ end
123
+
124
+ # Given a host, compute the relevant search domains for pre-existing
125
+ # cookies
126
+ def self.compute_search_domains_for_host host
127
+ host = effective_host host
128
+ result = [host]
129
+ unless host =~ IPADDR
130
+ result << ".#{host}"
131
+ base = hostname_reach host
132
+ if base
133
+ result << ".#{base}"
134
+ end
135
+ end
136
+ result
137
+ end
138
+
139
+ # Processes cookie domain data using the following rules:
140
+ # Domains strings of the form .foo.com match 'foo.com' and all immediate
141
+ # subdomains of 'foo.com'. Domain strings specified of the form 'foo.com' are
142
+ # modified to '.foo.com', and as such will still apply to subdomains.
143
+ #
144
+ # Cookies without an explicit domain will have their domain value taken directly
145
+ # from the URL, and will _NOT_ have any leading dot applied. For example, a request
146
+ # to http://foo.com/ will cause an entry for 'foo.com' to be created - which applies
147
+ # to foo.com but no subdomain.
148
+ #
149
+ # Note that this will not attempt to detect a mismatch of the request uri domain
150
+ # and explicitly specified cookie domain
151
+ def self.determine_cookie_domain request_uri, cookie_domain
152
+ uri = to_uri request_uri
153
+ domain = to_domain cookie_domain
154
+
155
+ if domain == nil || domain.empty?
156
+ domain = effective_host uri.host
157
+ else
158
+ domain = domain.downcase
159
+ if domain =~ IPADDR || domain.start_with?('.')
160
+ domain
161
+ else
162
+ ".#{domain}"
163
+ end
164
+ end
165
+ end
166
+
167
+ # Compute the effective host (RFC 2965, section 1)
168
+ # [host] a string or URI.
169
+ #
170
+ # Has the added additional logic of searching for interior dots specifically, and
171
+ # matches colons to prevent .local being suffixed on IPv6 addresses
172
+ def self.effective_host host_or_uri
173
+ hostname = to_domain host_or_uri
174
+ hostname = hostname.downcase
175
+
176
+ if /.[\.:]./.match(hostname) || hostname == '.local'
177
+ hostname
178
+ else
179
+ hostname + '.local'
180
+ end
181
+ end
182
+ # Check whether a cookie meets all of the rules to be created, based on
183
+ # its internal settings and the URI it came from.
184
+ #
185
+ # returns true on success, but will raise an InvalidCookieError on failure
186
+ # with an appropriate error message
187
+ def self.validate_cookie request_uri, cookie
188
+ uri = to_uri request_uri
189
+ request_host = effective_host uri.host
190
+ request_path = uri.path
191
+ request_secure = (uri.scheme == 'https')
192
+ cookie_host = cookie.domain
193
+ cookie_path = cookie.path
194
+
195
+ errors = []
196
+
197
+ # From RFC 2965, Section 3.3.2 Rejecting Cookies
198
+
199
+ # A user agent rejects (SHALL NOT store its information) if the
200
+ # Version attribute is missing. Note that the legacy Set-Cookie
201
+ # directive will result in an implicit version 0.
202
+ unless cookie.version
203
+ errors << "Version missing"
204
+ end
205
+
206
+ # The value for the Path attribute is not a prefix of the request-URI
207
+ unless request_path.start_with? cookie_path
208
+ errors << "Path is not a prefix of the request uri path"
209
+ end
210
+
211
+ unless cookie_host =~ IPADDR || #is an IPv4 or IPv6 address
212
+ cookie_host =~ /.\../ || #contains an embedded dot
213
+ cookie_host == '.local' #is the domain cookie for local addresses
214
+ errors << "Domain format is illegal"
215
+ end
216
+
217
+ # The effective host name that derives from the request-host does
218
+ # not domain-match the Domain attribute.
219
+ #
220
+ # The request-host is a HDN (not IP address) and has the form HD,
221
+ # where D is the value of the Domain attribute, and H is a string
222
+ # that contains one or more dots.
223
+ unless domains_match cookie_host, uri
224
+ errors << "Domain is inappropriate based on request URI hostname"
225
+ end
226
+
227
+ # The Port attribute has a "port-list", and the request-port was
228
+ # not in the list.
229
+ unless cookie.ports.nil? || cookie.ports.length != 0
230
+ unless cookie.ports.find_index uri.port
231
+ errors << "Ports list does not contain request URI port"
232
+ end
233
+ end
234
+
235
+ raise InvalidCookieError.new errors unless errors.empty?
236
+
237
+ # Note: 'secure' is not explicitly defined as an SSL channel, and no
238
+ # test is defined around validity and the 'secure' attribute
239
+ true
240
+ end
241
+ def self.parse_set_cookie set_cookie_value
242
+ args = { }
243
+ params=set_cookie_value.split /;\s*/
244
+ params.each do |param|
245
+ result = PARAM1.match param
246
+ if !result
247
+ raise InvalidCookieError.new "Invalid cookie parameter in cookie '#{set_cookie_value}'"
248
+ end
249
+ key = result[1].downcase.to_sym
250
+ keyvalue = result[2]
251
+ case key
252
+ when :expires
253
+ args[:expires_at] = Time.parse keyvalue
254
+ when :domain
255
+ args[:domain] = keyvalue
256
+ when :path
257
+ args[:path] = keyvalue
258
+ when :secure
259
+ args[:secure] = true
260
+ when :httponly
261
+ args[:http_only] = true
262
+ else
263
+ args[:name] = result[1]
264
+ args[:value] = keyvalue
265
+ end
266
+ end
267
+ args[:version] = 0
268
+ args
269
+ end
270
+ end
271
+ end