http-cookie 1.0.3 → 1.0.4

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: d1a93009a55673a4827d9f8d85c19b5c08f4b19c
4
- data.tar.gz: a7f4a3bb7a58ded55e6edac658cb20e0ad5d0821
2
+ SHA256:
3
+ metadata.gz: 6e3fc7cc6e374fa6bdd53c2a32cae8b8856615df4aad76fe496ab6375738652e
4
+ data.tar.gz: 0132bb41158fa3bf84a0adf2fcf7226115a1126efbc12c879f465a8c2114215b
5
5
  SHA512:
6
- metadata.gz: d46e2e2d42e8a5e7947ccb2b0eb187b930e1e1dcb5912b75ffd78aca7532af0b9144d0210b7ca46ec3c4d591cfd8c742b64e393c60fda814d7ce75ae2aaada26
7
- data.tar.gz: 5debdf55ddc8886db1e4e117e13829f6f93e2f08364126c0c693ed4dfde469374c49a35bef3f5b18455ab5379bf1289b386f30ebbae25603b4c5725beb2c231e
6
+ metadata.gz: 341c0b9947ed005f8c73030ad7b5380aa19d76cbfc2f3f09ac69207a9a5b33e62f0094f6b68b98ad839f110c565f7afc08a9ff504c82affe736a8bcb55908e05
7
+ data.tar.gz: c4346ce6bae86a394c72b38f079c3c272205df3b7453c630e1dc3fc1ae7dec7ee0f652c9b5f2b12151fb6b7b402a5fbc41b832c051cf17102bd1cd584f72b461
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## Unreleased
2
+
3
+ - Support Mozilla's cookie storage format up to version 7.
4
+
5
+ - Fix the time representation with creationTime and lastAccessed in
6
+ MozillaStore. (#8)
7
+
1
8
  ## 1.0.3 (2016-09-30)
2
9
 
3
10
  - Treat comma as normal character in HTTP::Cookie.cookie_value_to_hash
data/http-cookie.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |gem|
29
29
  gem.add_development_dependency("bundler", [">= 1.2.0"])
30
30
  gem.add_development_dependency("test-unit", [">= 2.4.3", *("< 3" if RUBY_VERSION < "1.9")])
31
31
  gem.add_development_dependency("rake", [">= 0.9.2.2", *("< 11" if RUBY_VERSION < "1.9")])
32
- gem.add_development_dependency("rdoc", ["> 2.4.2"])
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
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
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  class Cookie
3
- VERSION = "1.0.3"
3
+ VERSION = "1.0.4"
4
4
  end
5
5
  end
@@ -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
@@ -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
@@ -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,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-cookie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
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: 2016-09-30 00:00:00.000000000 Z
14
+ date: 2021-06-07 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: domain_name
@@ -156,7 +156,7 @@ 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
@@ -171,9 +171,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubyforge_project:
175
- rubygems_version: 2.6.6
176
- signing_key:
174
+ rubygems_version: 3.2.11
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: