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 +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:
|