http-cookie 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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: