http-cookie 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 633adcbc5625bcf9d8c1509b9480d955f3107a06
4
- data.tar.gz: 17c8fefbe45bb8429d3c533a1338bf4cec02345e
2
+ SHA256:
3
+ metadata.gz: 5230b0bd44e032652855e7b9e60e3d994ca56adbd57550c7520930d4dbf734a4
4
+ data.tar.gz: 65240197f49ac57bac8c6f3d1104cfe4f8fff77e1ac992c05c72d74efbba8300
5
5
  SHA512:
6
- metadata.gz: 190e3fc5a0a658b73a9fc6c0e43937b6fd9fdebb9b6d92e09edd51c24209fbd2fb61e9ea49eb29621f2fefeb1ec5095779deded65c343f2f0c52c4f53c1e0b76
7
- data.tar.gz: 96627fd5e6617b71c0b5dadf08e918169aabeda0c9ebf0f3a3d1d3d4c920b3999637f61009f4d531ddb588178bd6f0e26529b9ee49bf1808374971b7337a69f3
6
+ metadata.gz: 7fc5bb2e287d60d060c54eb9fb9ccb6d55c55e84ec35525deff8c088c873d6ac26db86f7f1cf3c03a7cbf05e397b6cd0e3a1e1171c2dcff8848e0345a34b0905
7
+ data.tar.gz: 1c85e07a65fac1d5440126bea27dbc01160edc9a791f56e021cd3142070eada54bf1ec3cda31c9d9273f23c3a84c8786c308bcdd27e03f7266c203dde4abdd6f
@@ -0,0 +1,37 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+ branches:
9
+ - "*"
10
+
11
+ jobs:
12
+ test:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os: [ubuntu]
17
+ # We still kind of support Ruby 1.8.7
18
+ ruby: [2.7, "3.0", 3.1, head, jruby]
19
+
20
+ name: >-
21
+ ${{matrix.os}}:ruby-${{matrix.ruby}}
22
+ runs-on: ${{matrix.os}}-latest
23
+ continue-on-error: ${{matrix.ruby == 'head' || matrix.ruby == 'jruby'}}
24
+
25
+ steps:
26
+ - name: Check out
27
+ uses: actions/checkout@v2
28
+
29
+ - name: Set up ruby and bundle
30
+ uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{matrix.ruby}}
33
+ bundler-cache: true
34
+
35
+ - name: Run rake
36
+ run: |
37
+ bundle exec rake
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 1.0.5 (2022-05-25)
2
+
3
+ - Silence SQLite3 warnings
4
+
5
+ ## 1.0.4 (2021-06-07)
6
+
7
+ - Support Mozilla's cookie storage format up to version 7.
8
+
9
+ - Fix the time representation with creationTime and lastAccessed in
10
+ MozillaStore. (#8)
11
+
12
+ ## 1.0.3 (2016-09-30)
13
+
14
+ - Treat comma as normal character in HTTP::Cookie.cookie_value_to_hash
15
+ instead of key-value pair separator. This should fix the problem
16
+ described in CVE-2016-7401.
17
+
1
18
  ## 1.0.2 (2013-09-10)
2
19
 
3
20
  - Fix HTTP::Cookie.parse so that it does not raise ArgumentError
data/http-cookie.gemspec CHANGED
@@ -25,10 +25,11 @@ Gem::Specification.new do |gem|
25
25
  gem.extra_rdoc_files = ['README.md', 'LICENSE.txt']
26
26
 
27
27
  gem.add_runtime_dependency("domain_name", ["~> 0.5"])
28
- gem.add_development_dependency("sqlite3", ["~> 1.3.3"]) unless defined?(JRUBY_VERSION)
28
+ gem.add_development_dependency("sqlite3", ["~> 1.3"]) unless defined?(JRUBY_VERSION)
29
29
  gem.add_development_dependency("bundler", [">= 1.2.0"])
30
- gem.add_development_dependency("test-unit", [">= 2.4.3"])
31
- gem.add_development_dependency("rake", [">= 0.9.2.2"])
32
- gem.add_development_dependency("rdoc", ["> 2.4.2"])
30
+ gem.add_development_dependency("test-unit", [">= 2.4.3", *("< 3" if RUBY_VERSION < "1.9")])
31
+ gem.add_development_dependency("rake", [">= 0.9.2.2", *("< 11" if RUBY_VERSION < "1.9")])
32
+ gem.add_development_dependency("rdoc", RUBY_VERSION > "1.9" ? "> 2.4.2" : "~> 2.4.2")
33
33
  gem.add_development_dependency("simplecov", [">= 0"])
34
+ gem.add_development_dependency("json", ["< 2"]) if RUBY_VERSION < "2.0"
34
35
  end
@@ -50,7 +50,7 @@ class HTTP::Cookie::Scanner < StringScanner
50
50
  }
51
51
  end
52
52
 
53
- def scan_value
53
+ def scan_value(comma_as_separator = false)
54
54
  ''.tap { |s|
55
55
  case
56
56
  when scan(/[^,;"]+/)
@@ -59,7 +59,9 @@ class HTTP::Cookie::Scanner < StringScanner
59
59
  # RFC 6265 2.2
60
60
  # A cookie-value may be DQUOTE'd.
61
61
  s << scan_dquoted
62
- when check(/;|#{RE_COOKIE_COMMA}/o)
62
+ when check(/;/)
63
+ break
64
+ when comma_as_separator && check(RE_COOKIE_COMMA)
63
65
  break
64
66
  else
65
67
  s << getch
@@ -68,12 +70,12 @@ class HTTP::Cookie::Scanner < StringScanner
68
70
  }
69
71
  end
70
72
 
71
- def scan_name_value
73
+ def scan_name_value(comma_as_separator = false)
72
74
  name = scan_name
73
75
  if skip(/\=/)
74
- value = scan_value
76
+ value = scan_value(comma_as_separator)
75
77
  else
76
- scan_value
78
+ scan_value(comma_as_separator)
77
79
  value = nil
78
80
  end
79
81
  [name, value]
@@ -159,7 +161,7 @@ class HTTP::Cookie::Scanner < StringScanner
159
161
 
160
162
  skip_wsp
161
163
 
162
- name, value = scan_name_value
164
+ name, value = scan_name_value(true)
163
165
  if value.nil?
164
166
  @logger.warn("Cookie definition lacks a name-value pair.") if @logger
165
167
  elsif name.empty?
@@ -176,7 +178,7 @@ class HTTP::Cookie::Scanner < StringScanner
176
178
  break
177
179
  when skip(/;/)
178
180
  skip_wsp
179
- aname, avalue = scan_name_value
181
+ aname, avalue = scan_name_value(true)
180
182
  next if aname.empty? || value.nil?
181
183
  aname.downcase!
182
184
  case aname
@@ -218,13 +220,12 @@ class HTTP::Cookie::Scanner < StringScanner
218
220
  until eos?
219
221
  skip_wsp
220
222
 
221
- name, value = scan_name_value
223
+ # Do not treat comma in a Cookie header value as separator; see CVE-2016-7401
224
+ name, value = scan_name_value(false)
222
225
 
223
226
  yield name, value if value
224
227
 
225
- # The comma is used as separator for concatenating multiple
226
- # values of a header.
227
- skip(/[;,]/)
228
+ skip(/;/)
228
229
  end
229
230
  end
230
231
  end
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  class Cookie
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.5"
4
4
  end
5
5
  end
data/lib/http/cookie.rb CHANGED
@@ -128,7 +128,7 @@ class HTTP::Cookie
128
128
  # new("name" => "uid", "value" => "a12345", "Domain" => 'www.example.org')
129
129
  #
130
130
  def initialize(*args)
131
- @origin = @domain = @path =
131
+ @name = @origin = @domain = @path =
132
132
  @expires = @max_age = nil
133
133
  @for_domain = @secure = @httponly = false
134
134
  @session = true
@@ -17,8 +17,8 @@ class HTTP::CookieJar::AbstractStore
17
17
  begin
18
18
  require 'http/cookie_jar/%s_store' % symbol
19
19
  @@class_map.fetch(symbol)
20
- rescue LoadError, IndexError
21
- raise IndexError, 'cookie store unavailable: %s' % symbol.inspect
20
+ rescue LoadError, IndexError => e
21
+ raise IndexError, 'cookie store unavailable: %s, error: %s' % symbol.inspect, e.message
22
22
  end
23
23
  end
24
24
 
@@ -67,10 +67,8 @@ class HTTP::CookieJar
67
67
  def each(uri = nil) # :yield: cookie
68
68
  now = Time.now
69
69
  if uri
70
- thost = DomainName.new(uri.host)
71
70
  tpath = uri.path
72
71
  @jar.each { |domain, paths|
73
- next unless thost.cookie_domain?(domain)
74
72
  paths.each { |path, hash|
75
73
  next unless HTTP::Cookie.path_match?(path, tpath)
76
74
  hash.delete_if { |name, cookie|
@@ -10,7 +10,7 @@ class HTTP::CookieJar
10
10
  # stored persistently in the SQLite3 database.
11
11
  class MozillaStore < AbstractStore
12
12
  # :stopdoc:
13
- SCHEMA_VERSION = 5
13
+ SCHEMA_VERSION = 7
14
14
 
15
15
  def default_options
16
16
  {
@@ -22,14 +22,11 @@ class HTTP::CookieJar
22
22
 
23
23
  ALL_COLUMNS = %w[
24
24
  baseDomain
25
- appId inBrowserElement
25
+ originAttributes
26
26
  name value
27
27
  host path
28
28
  expiry creationTime lastAccessed
29
29
  isSecure isHttpOnly
30
- ]
31
- UK_COLUMNS = %w[
32
- name host path
33
30
  appId inBrowserElement
34
31
  ]
35
32
 
@@ -95,6 +92,11 @@ class HTTP::CookieJar
95
92
  def initialize(options = nil)
96
93
  super
97
94
 
95
+ @origin_attributes = encode_www_form({}.tap { |params|
96
+ params['appId'] = @app_id if @app_id.nonzero?
97
+ params['inBrowserElement'] = 1 if @in_browser_element
98
+ })
99
+
98
100
  @filename = options[:filename] or raise ArgumentError, ':filename option is missing'
99
101
 
100
102
  @sjar = HTTP::CookieJar::HashStore.new
@@ -134,7 +136,7 @@ class HTTP::CookieJar
134
136
 
135
137
  # Returns the schema version of the database.
136
138
  def schema_version
137
- @schema_version ||= @db.execute("PRAGMA user_version").first[0]
139
+ @schema_version ||= @db.execute("PRAGMA user_version").first["user_version"]
138
140
  rescue SQLite3::SQLException
139
141
  @logger.warn "couldn't get schema version!" if @logger
140
142
  return nil
@@ -147,8 +149,8 @@ class HTTP::CookieJar
147
149
  @schema_version = version
148
150
  end
149
151
 
150
- def create_table
151
- self.schema_version = SCHEMA_VERSION
152
+ def create_table_v5
153
+ self.schema_version = 5
152
154
  @db.execute("DROP TABLE IF EXISTS moz_cookies")
153
155
  @db.execute(<<-'SQL')
154
156
  CREATE TABLE moz_cookies (
@@ -176,6 +178,62 @@ class HTTP::CookieJar
176
178
  SQL
177
179
  end
178
180
 
181
+ def create_table_v6
182
+ self.schema_version = 6
183
+ @db.execute("DROP TABLE IF EXISTS moz_cookies")
184
+ @db.execute(<<-'SQL')
185
+ CREATE TABLE moz_cookies (
186
+ id INTEGER PRIMARY KEY,
187
+ baseDomain TEXT,
188
+ originAttributes TEXT NOT NULL DEFAULT '',
189
+ name TEXT,
190
+ value TEXT,
191
+ host TEXT,
192
+ path TEXT,
193
+ expiry INTEGER,
194
+ lastAccessed INTEGER,
195
+ creationTime INTEGER,
196
+ isSecure INTEGER,
197
+ isHttpOnly INTEGER,
198
+ CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)
199
+ )
200
+ SQL
201
+ @db.execute(<<-'SQL')
202
+ CREATE INDEX moz_basedomain
203
+ ON moz_cookies (baseDomain,
204
+ originAttributes);
205
+ SQL
206
+ end
207
+
208
+ def create_table
209
+ self.schema_version = SCHEMA_VERSION
210
+ @db.execute("DROP TABLE IF EXISTS moz_cookies")
211
+ @db.execute(<<-'SQL')
212
+ CREATE TABLE moz_cookies (
213
+ id INTEGER PRIMARY KEY,
214
+ baseDomain TEXT,
215
+ originAttributes TEXT NOT NULL DEFAULT '',
216
+ name TEXT,
217
+ value TEXT,
218
+ host TEXT,
219
+ path TEXT,
220
+ expiry INTEGER,
221
+ lastAccessed INTEGER,
222
+ creationTime INTEGER,
223
+ isSecure INTEGER,
224
+ isHttpOnly INTEGER,
225
+ appId INTEGER DEFAULT 0,
226
+ inBrowserElement INTEGER DEFAULT 0,
227
+ CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)
228
+ )
229
+ SQL
230
+ @db.execute(<<-'SQL')
231
+ CREATE INDEX moz_basedomain
232
+ ON moz_cookies (baseDomain,
233
+ originAttributes);
234
+ SQL
235
+ end
236
+
179
237
  def db_prepare(sql)
180
238
  st = @db.prepare(sql)
181
239
  yield st
@@ -226,7 +284,7 @@ class HTTP::CookieJar
226
284
  when 4
227
285
  @db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
228
286
  @db.execute("DROP INDEX moz_basedomain")
229
- create_table
287
+ create_table_v5
230
288
  @db.execute(<<-'SQL')
231
289
  INSERT INTO moz_cookies
232
290
  (baseDomain, appId, inBrowserElement, name, value, host, path, expiry,
@@ -236,7 +294,42 @@ class HTTP::CookieJar
236
294
  FROM moz_cookies_old
237
295
  SQL
238
296
  @db.execute("DROP TABLE moz_cookies_old")
297
+ when 5
298
+ @db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
299
+ @db.execute("DROP INDEX moz_basedomain")
300
+ create_table_v6
301
+ @db.create_function('CONVERT_TO_ORIGIN_ATTRIBUTES', 2) { |func, appId, inBrowserElement|
302
+ params = {}
303
+ params['appId'] = appId if appId.nonzero?
304
+ params['inBrowserElement'] = inBrowserElement if inBrowserElement.nonzero?
305
+ func.result = encode_www_form(params)
306
+ }
307
+ @db.execute(<<-'SQL')
308
+ INSERT INTO moz_cookies
309
+ (baseDomain, originAttributes, name, value, host, path, expiry,
310
+ lastAccessed, creationTime, isSecure, isHttpOnly)
311
+ SELECT baseDomain,
312
+ CONVERT_TO_ORIGIN_ATTRIBUTES(appId, inBrowserElement),
313
+ name, value, host, path, expiry, lastAccessed, creationTime,
314
+ isSecure, isHttpOnly
315
+ FROM moz_cookies_old
316
+ SQL
317
+ @db.execute("DROP TABLE moz_cookies_old")
318
+ when 6
319
+ @db.execute("ALTER TABLE moz_cookies ADD appId INTEGER DEFAULT 0")
320
+ @db.execute("ALTER TABLE moz_cookies ADD inBrowserElement INTEGER DEFAULT 0")
321
+ @db.create_function('SET_APP_ID', 1) { |func, originAttributes|
322
+ func.result = get_query_param(originAttributes, 'appId').to_i # nil.to_i == 0
323
+ }
324
+ @db.create_function('SET_IN_BROWSER', 1) { |func, originAttributes|
325
+ func.result = get_query_param(originAttributes, 'inBrowserElement').to_i # nil.to_i == 0
326
+ }
327
+ @db.execute(<<-'SQL')
328
+ UPDATE moz_cookies SET appId = SET_APP_ID(originAttributes),
329
+ inBrowserElement = SET_IN_BROWSER(originAttributes)
330
+ SQL
239
331
  @logger.info("Upgraded database to schema version %d" % schema_version) if @logger
332
+ self.schema_version += 1
240
333
  else
241
334
  break
242
335
  end
@@ -259,16 +352,17 @@ class HTTP::CookieJar
259
352
  def db_add(cookie)
260
353
  @stmt[:add].execute({
261
354
  :baseDomain => cookie.domain_name.domain || cookie.domain,
262
- :appId => @app_id,
263
- :inBrowserElement => @in_browser_element ? 1 : 0,
355
+ :originAttributes => @origin_attributes,
264
356
  :name => cookie.name, :value => cookie.value,
265
357
  :host => cookie.dot_domain,
266
358
  :path => cookie.path,
267
359
  :expiry => cookie.expires_at.to_i,
268
- :creationTime => cookie.created_at.to_i,
269
- :lastAccessed => cookie.accessed_at.to_i,
360
+ :creationTime => serialize_usectime(cookie.created_at),
361
+ :lastAccessed => serialize_usectime(cookie.accessed_at),
270
362
  :isSecure => cookie.secure? ? 1 : 0,
271
363
  :isHttpOnly => cookie.httponly? ? 1 : 0,
364
+ :appId => @app_id,
365
+ :inBrowserElement => @in_browser_element ? 1 : 0,
272
366
  })
273
367
  cleanup if (@gc_index += 1) >= @gc_threshold
274
368
 
@@ -295,6 +389,36 @@ class HTTP::CookieJar
295
389
  self
296
390
  end
297
391
 
392
+ if RUBY_VERSION >= '1.9'
393
+ def encode_www_form(enum)
394
+ URI.encode_www_form(enum)
395
+ end
396
+
397
+ def get_query_param(str, key)
398
+ URI.decode_www_form(str).find { |k, v|
399
+ break v if k == key
400
+ }
401
+ end
402
+ else
403
+ require 'cgi'
404
+
405
+ def encode_www_form(enum)
406
+ enum.map { |k, v| "#{CGI.escape(k)}=#{CGI.escape(v)}" }.join('&')
407
+ end
408
+
409
+ def get_query_param(str, key)
410
+ CGI.parse(str)[key].first
411
+ end
412
+ end
413
+
414
+ def serialize_usectime(time)
415
+ time ? (time.to_f * 1e6).floor : 0
416
+ end
417
+
418
+ def deserialize_usectime(value)
419
+ Time.at(value ? value / 1e6 : 0)
420
+ end
421
+
298
422
  public
299
423
 
300
424
  def add(cookie)
@@ -337,7 +461,6 @@ class HTTP::CookieJar
337
461
  now = Time.now
338
462
  if uri
339
463
  thost = DomainName.new(uri.host)
340
- tpath = uri.path
341
464
 
342
465
  @stmt[:cookies_for_domain].execute({
343
466
  :baseDomain => thost.domain || thost.hostname,
@@ -355,8 +478,8 @@ class HTTP::CookieJar
355
478
  attrs[:domain] = row['host']
356
479
  attrs[:path] = row['path']
357
480
  attrs[:expires_at] = Time.at(row['expiry'])
358
- attrs[:accessed_at] = Time.at(row['lastAccessed'] || 0)
359
- attrs[:created_at] = Time.at(row['creationTime'] || 0)
481
+ attrs[:accessed_at] = deserialize_usectime(row['lastAccessed'])
482
+ attrs[:created_at] = deserialize_usectime(row['creationTime'])
360
483
  attrs[:secure] = secure
361
484
  attrs[:httponly] = row['isHttpOnly'] != 0
362
485
  })
@@ -364,7 +487,7 @@ class HTTP::CookieJar
364
487
  if cookie.valid_for_uri?(uri)
365
488
  cookie.accessed_at = now
366
489
  @stmt[:update_lastaccessed].execute({
367
- 'lastAccessed' => now.to_i,
490
+ 'lastAccessed' => serialize_usectime(now),
368
491
  'id' => row['id'],
369
492
  })
370
493
  yield cookie
@@ -383,8 +506,8 @@ class HTTP::CookieJar
383
506
  attrs[:domain] = row['host']
384
507
  attrs[:path] = row['path']
385
508
  attrs[:expires_at] = Time.at(row['expiry'])
386
- attrs[:accessed_at] = Time.at(row['lastAccessed'] || 0)
387
- attrs[:created_at] = Time.at(row['creationTime'] || 0)
509
+ attrs[:accessed_at] = deserialize_usectime(row['lastAccessed'])
510
+ attrs[:created_at] = deserialize_usectime(row['creationTime'])
388
511
  attrs[:secure] = row['isSecure'] != 0
389
512
  attrs[:httponly] = row['isHttpOnly'] != 0
390
513
  })
@@ -21,7 +21,7 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
21
21
 
22
22
  def load(io, jar)
23
23
  begin
24
- data = YAML.load(io)
24
+ data = load_yaml(io)
25
25
  rescue ArgumentError => e
26
26
  case e.message
27
27
  when %r{\Aundefined class/module Mechanize::}
@@ -31,7 +31,7 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
31
31
  yaml = io.read
32
32
  # a gross hack
33
33
  yaml.gsub!(%r{^( [^ ].*:) !ruby/object:Mechanize::Cookie$}, "\\1")
34
- data = YAML.load(yaml)
34
+ data = load_yaml(yaml)
35
35
  rescue Errno::ESPIPE
36
36
  @logger.warn "could not rewind the stream for conversion" if @logger
37
37
  rescue ArgumentError
@@ -73,4 +73,14 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
73
73
  def default_options
74
74
  {}
75
75
  end
76
+
77
+ if YAML.name == 'Psych' && Psych::VERSION >= '3.1'
78
+ def load_yaml(yaml)
79
+ YAML.safe_load(yaml, :permitted_classes => %w[Time HTTP::Cookie Mechanize::Cookie DomainName], :aliases => true)
80
+ end
81
+ else
82
+ def load_yaml(yaml)
83
+ YAML.load(yaml)
84
+ end
85
+ end
76
86
  end
@@ -1,5 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require File.expand_path('helper', File.dirname(__FILE__))
3
+ require 'psych' if !defined?(YAML) && RUBY_VERSION == "1.9.2"
4
+ require 'yaml'
3
5
 
4
6
  class TestHTTPCookie < Test::Unit::TestCase
5
7
  def setup
@@ -441,17 +443,28 @@ class TestHTTPCookie < Test::Unit::TestCase
441
443
  ['Bar', 'value 2'],
442
444
  ['Baz', 'value3'],
443
445
  ['Bar', 'value"4'],
446
+ ['Quux', 'x, value=5'],
444
447
  ]
445
448
 
446
449
  cookie_value = HTTP::Cookie.cookie_value(pairs.map { |name, value|
447
450
  HTTP::Cookie.new(:name => name, :value => value)
448
451
  })
449
452
 
450
- assert_equal 'Foo=value1; Bar="value 2"; Baz=value3; Bar="value\\"4"', cookie_value
453
+ assert_equal 'Foo=value1; Bar="value 2"; Baz=value3; Bar="value\\"4"; Quux="x, value=5"', cookie_value
451
454
 
452
455
  hash = HTTP::Cookie.cookie_value_to_hash(cookie_value)
453
456
 
454
- assert_equal 3, hash.size
457
+ assert_equal pairs.map(&:first).uniq.size, hash.size
458
+
459
+ hash.each_pair { |name, value|
460
+ _, pvalue = pairs.assoc(name)
461
+ assert_equal pvalue, value
462
+ }
463
+
464
+ # Do not treat comma in a Cookie header value as separator; see CVE-2016-7401
465
+ hash = HTTP::Cookie.cookie_value_to_hash('Quux=x, value=5; Foo=value1; Bar="value 2"; Baz=value3; Bar="value\\"4"')
466
+
467
+ assert_equal pairs.map(&:first).uniq.size, hash.size
455
468
 
456
469
  hash.each_pair { |name, value|
457
470
  _, pvalue = pairs.assoc(name)
@@ -1062,6 +1075,16 @@ class TestHTTPCookie < Test::Unit::TestCase
1062
1075
  }
1063
1076
  end
1064
1077
 
1078
+ if YAML.name == 'Psych' && Psych::VERSION >= '3.1'
1079
+ private def load_yaml(yaml)
1080
+ YAML.safe_load(yaml, :permitted_classes => %w[Time HTTP::Cookie Mechanize::Cookie DomainName], :aliases => true)
1081
+ end
1082
+ else
1083
+ private def load_yaml(yaml)
1084
+ YAML.load(yaml)
1085
+ end
1086
+ end
1087
+
1065
1088
  def test_yaml_expires
1066
1089
  require 'yaml'
1067
1090
  cookie = HTTP::Cookie.new(cookie_values)
@@ -1069,29 +1092,29 @@ class TestHTTPCookie < Test::Unit::TestCase
1069
1092
  assert_equal false, cookie.session?
1070
1093
  assert_equal nil, cookie.max_age
1071
1094
 
1072
- ycookie = YAML.load(cookie.to_yaml)
1095
+ ycookie = load_yaml(cookie.to_yaml)
1073
1096
  assert_equal false, ycookie.session?
1074
1097
  assert_equal nil, ycookie.max_age
1075
1098
  assert_in_delta cookie.expires, ycookie.expires, 1
1076
1099
 
1077
1100
  cookie.expires = nil
1078
- ycookie = YAML.load(cookie.to_yaml)
1101
+ ycookie = load_yaml(cookie.to_yaml)
1079
1102
  assert_equal true, ycookie.session?
1080
1103
  assert_equal nil, ycookie.max_age
1081
1104
 
1082
1105
  cookie.expires = Time.now + 3600
1083
- ycookie = YAML.load(cookie.to_yaml)
1106
+ ycookie = load_yaml(cookie.to_yaml)
1084
1107
  assert_equal false, ycookie.session?
1085
1108
  assert_equal nil, ycookie.max_age
1086
1109
  assert_in_delta cookie.expires, ycookie.expires, 1
1087
1110
 
1088
1111
  cookie.max_age = 3600
1089
- ycookie = YAML.load(cookie.to_yaml)
1112
+ ycookie = load_yaml(cookie.to_yaml)
1090
1113
  assert_equal false, ycookie.session?
1091
1114
  assert_in_delta cookie.created_at + 3600, ycookie.expires, 1
1092
1115
 
1093
1116
  cookie.max_age = nil
1094
- ycookie = YAML.load(cookie.to_yaml)
1117
+ ycookie = load_yaml(cookie.to_yaml)
1095
1118
  assert_equal true, ycookie.session?
1096
1119
  assert_equal nil, ycookie.expires
1097
1120
  end
@@ -20,11 +20,7 @@ module TestHTTPCookieJar
20
20
  assert_raises(NameError) {
21
21
  HTTP::CookieJar::ErroneousStore
22
22
  }
23
- if RUBY_VERSION >= "1.9"
24
- assert_includes $LOADED_FEATURES, rb
25
- else
26
- assert_includes $LOADED_FEATURES, rb[(dir.size + 1)..-1]
27
- end
23
+ assert($LOADED_FEATURES.any? { |file| FileTest.identical?(file, rb) })
28
24
  }
29
25
  end
30
26
 
@@ -45,11 +41,7 @@ module TestHTTPCookieJar
45
41
  assert_raises(NameError) {
46
42
  HTTP::CookieJar::ErroneousSaver
47
43
  }
48
- if RUBY_VERSION >= "1.9"
49
- assert_includes $LOADED_FEATURES, rb
50
- else
51
- assert_includes $LOADED_FEATURES, rb[(dir.size + 1)..-1]
52
- end
44
+ assert($LOADED_FEATURES.any? { |file| FileTest.identical?(file, rb) })
53
45
  }
54
46
  end
55
47
  end
@@ -139,6 +131,17 @@ module TestHTTPCookieJar
139
131
  assert_equal(0, @jar.cookies(URI('http://www.rubyforge.org/')).length)
140
132
  end
141
133
 
134
+ def test_host_only_with_unqualified_hostname
135
+ @jar.add(HTTP::Cookie.new(cookie_values(
136
+ :origin => 'http://localhost/', :domain => 'localhost', :for_domain => false)))
137
+
138
+ assert_equal(1, @jar.cookies(URI('http://localhost/')).length)
139
+
140
+ assert_equal(1, @jar.cookies(URI('http://Localhost/')).length)
141
+
142
+ assert_equal(1, @jar.cookies(URI('https://Localhost/')).length)
143
+ end
144
+
142
145
  def test_empty_value
143
146
  url = URI 'http://rubyforge.org/'
144
147
  values = cookie_values(:value => "")
metadata CHANGED
@@ -1,114 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-cookie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinori MUSHA
8
8
  - Aaron Patterson
9
9
  - Eric Hodel
10
10
  - Mike Dalessio
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-09-10 00:00:00.000000000 Z
14
+ date: 2022-05-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: domain_name
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - ~>
20
+ - - "~>"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '0.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ~>
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.5'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: sqlite3
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - ~>
34
+ - - "~>"
35
35
  - !ruby/object:Gem::Version
36
- version: 1.3.3
36
+ version: '1.3'
37
37
  type: :development
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - ~>
41
+ - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: 1.3.3
43
+ version: '1.3'
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: bundler
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - '>='
48
+ - - ">="
49
49
  - !ruby/object:Gem::Version
50
50
  version: 1.2.0
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - '>='
55
+ - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: 1.2.0
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: test-unit
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
- - - '>='
62
+ - - ">="
63
63
  - !ruby/object:Gem::Version
64
64
  version: 2.4.3
65
65
  type: :development
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - '>='
69
+ - - ">="
70
70
  - !ruby/object:Gem::Version
71
71
  version: 2.4.3
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: rake
74
74
  requirement: !ruby/object:Gem::Requirement
75
75
  requirements:
76
- - - '>='
76
+ - - ">="
77
77
  - !ruby/object:Gem::Version
78
78
  version: 0.9.2.2
79
79
  type: :development
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - '>='
83
+ - - ">="
84
84
  - !ruby/object:Gem::Version
85
85
  version: 0.9.2.2
86
86
  - !ruby/object:Gem::Dependency
87
87
  name: rdoc
88
88
  requirement: !ruby/object:Gem::Requirement
89
89
  requirements:
90
- - - '>'
90
+ - - ">"
91
91
  - !ruby/object:Gem::Version
92
92
  version: 2.4.2
93
93
  type: :development
94
94
  prerelease: false
95
95
  version_requirements: !ruby/object:Gem::Requirement
96
96
  requirements:
97
- - - '>'
97
+ - - ">"
98
98
  - !ruby/object:Gem::Version
99
99
  version: 2.4.2
100
100
  - !ruby/object:Gem::Dependency
101
101
  name: simplecov
102
102
  requirement: !ruby/object:Gem::Requirement
103
103
  requirements:
104
- - - '>='
104
+ - - ">="
105
105
  - !ruby/object:Gem::Version
106
106
  version: '0'
107
107
  type: :development
108
108
  prerelease: false
109
109
  version_requirements: !ruby/object:Gem::Requirement
110
110
  requirements:
111
- - - '>='
111
+ - - ">="
112
112
  - !ruby/object:Gem::Version
113
113
  version: '0'
114
114
  description: HTTP::Cookie is a Ruby library to handle HTTP Cookies based on RFC 6265. It
@@ -127,8 +127,8 @@ extra_rdoc_files:
127
127
  - README.md
128
128
  - LICENSE.txt
129
129
  files:
130
- - .gitignore
131
- - .travis.yml
130
+ - ".github/workflows/ci.yml"
131
+ - ".gitignore"
132
132
  - CHANGELOG.md
133
133
  - Gemfile
134
134
  - LICENSE.txt
@@ -156,24 +156,23 @@ homepage: https://github.com/sparklemotion/http-cookie
156
156
  licenses:
157
157
  - MIT
158
158
  metadata: {}
159
- post_install_message:
159
+ post_install_message:
160
160
  rdoc_options: []
161
161
  require_paths:
162
162
  - lib
163
163
  required_ruby_version: !ruby/object:Gem::Requirement
164
164
  requirements:
165
- - - '>='
165
+ - - ">="
166
166
  - !ruby/object:Gem::Version
167
167
  version: '0'
168
168
  required_rubygems_version: !ruby/object:Gem::Requirement
169
169
  requirements:
170
- - - '>='
170
+ - - ">="
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubyforge_project:
175
- rubygems_version: 2.0.3
176
- signing_key:
174
+ rubygems_version: 3.3.14
175
+ signing_key:
177
176
  specification_version: 4
178
177
  summary: A Ruby library to handle HTTP Cookies based on RFC 6265
179
178
  test_files:
data/.travis.yml DELETED
@@ -1,17 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.8.7
4
- - ree
5
- - 1.9.3
6
- - 2.0.0
7
- - ruby-head
8
- - jruby-18mode
9
- - jruby-19mode
10
- - jruby-head
11
- - rbx-18mode
12
- - rbx-19mode
13
- matrix:
14
- allow_failures:
15
- - rvm: ruby-head
16
- - rvm: rbx-18mode
17
- - rvm: rbx-19mode