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 +5 -5
- data/CHANGELOG.md +7 -0
- data/http-cookie.gemspec +2 -1
- data/lib/http/cookie.rb +1 -1
- data/lib/http/cookie/version.rb +1 -1
- data/lib/http/cookie_jar/abstract_store.rb +2 -2
- data/lib/http/cookie_jar/hash_store.rb +0 -2
- data/lib/http/cookie_jar/mozilla_store.rb +141 -18
- data/lib/http/cookie_jar/yaml_saver.rb +12 -2
- data/test/test_http_cookie_jar.rb +13 -10
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6e3fc7cc6e374fa6bdd53c2a32cae8b8856615df4aad76fe496ab6375738652e
|
4
|
+
data.tar.gz: 0132bb41158fa3bf84a0adf2fcf7226115a1126efbc12c879f465a8c2114215b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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",
|
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
|
data/lib/http/cookie/version.rb
CHANGED
@@ -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 =
|
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
|
-
|
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
|
151
|
-
self.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
|
-
|
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
|
-
:
|
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
|
269
|
-
:lastAccessed => cookie.accessed_at
|
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] =
|
359
|
-
attrs[:created_at] =
|
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
|
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] =
|
387
|
-
attrs[:created_at] =
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
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.
|
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:
|
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
|
-
|
175
|
-
|
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:
|