http-cookie 1.0.0.pre2 → 1.0.0.pre3

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
2
  SHA1:
3
- metadata.gz: 653d322460f46234180a90aed35776cd7cd8de38
4
- data.tar.gz: 14c9c551e73f83be713b128d4ae0a0cd0211d9f0
3
+ metadata.gz: 38b7c03ef15bbe6b866f7128b719962c7776fa16
4
+ data.tar.gz: 79078f90e4250e68ec2fa0b6250ee378d7681aea
5
5
  SHA512:
6
- metadata.gz: 528f89eca80703fec30058de9b9772fc0fb83962d6aa17fe07977b8cbb109fe62f63989097520d955f8b70576bc63ea0c3815195d2d6717bfe1d46a87257cfe4
7
- data.tar.gz: 4bf6f20da6f6dc7bfe5ec5980c7298f70c1ebc39024abad55b47d8c9b897d5dfc73f2a4216324ac0e6d884f930e6b401e57cefde0666dc2f88079d0508348b79
6
+ metadata.gz: 41d93c054cda8e2fbb07554de72061fcf6218da13dce541fda0581056315b0d0438307c1f95043d59bce7742e4cee08ea9295f75c7fc1ddf297849cf7ed87ee0
7
+ data.tar.gz: a9cebb93040062c160bccf8758a25898af16f8b8fc2e5118a5cfb7210ba96b2f212b8154ca2b4e1fb1e2e740a5efaffd515bd9addc0ddee3be94d6e93e89f7f9
data/http-cookie.gemspec CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |gem|
24
24
  gem.extra_rdoc_files = ['README.md', 'LICENSE.txt']
25
25
 
26
26
  gem.add_runtime_dependency("domain_name", ["~> 0.5"])
27
+ gem.add_runtime_dependency("sqlite3", ["~> 1.3.3"])
27
28
  gem.add_development_dependency("bundler", [">= 1.2.0"])
28
29
  gem.add_development_dependency("test-unit", [">= 2.4.3"])
29
30
  gem.add_development_dependency("rake", [">= 0.9.2.2"])
data/lib/http/cookie.rb CHANGED
@@ -386,6 +386,12 @@ class HTTP::Cookie
386
386
  @domain = @domain_name.hostname
387
387
  end
388
388
 
389
+ # Returns the domain, with a dot prefixed only if the domain flag is
390
+ # on.
391
+ def dot_domain
392
+ @for_domain ? '.' << @domain : @domain
393
+ end
394
+
389
395
  # Returns the domain attribute value as a DomainName object.
390
396
  attr_reader :domain_name
391
397
 
@@ -1,5 +1,5 @@
1
1
  module HTTP
2
2
  class Cookie
3
- VERSION = "1.0.0.pre2"
3
+ VERSION = "1.0.0.pre3"
4
4
  end
5
5
  end
@@ -13,6 +13,8 @@ class HTTP::CookieJar
13
13
  # Generates a new cookie jar. The default store class is `:hash`,
14
14
  # which maps to `HTTP::CookieJar::HashStore`. Any given options are
15
15
  # passed through to the initializer of the specified store class.
16
+ # For example, the `:mozilla` (`HTTP::CookieJar::MozillaStore`)
17
+ # store class requires a `:filename` option.
16
18
  def initialize(store = :hash, options = nil)
17
19
  case store
18
20
  when Symbol
@@ -95,9 +97,6 @@ class HTTP::CookieJar
95
97
  if uri
96
98
  uri = URI(uri)
97
99
  return self unless URI::HTTP === uri && uri.host
98
- block = proc { |cookie|
99
- yield cookie if cookie.valid_for_uri?(uri)
100
- }
101
100
  end
102
101
 
103
102
  @store.each(uri, &block)
@@ -28,11 +28,14 @@ class HTTP::CookieJar::CookiestxtSaver < HTTP::CookieJar::AbstractSaver
28
28
  }
29
29
  end
30
30
 
31
+ HTTPONLY_PREFIX = '#HttpOnly_'
32
+ RE_HTTPONLY_PREFIX = /\A#{HTTPONLY_PREFIX}/
33
+
31
34
  # Serializes the cookie into a cookies.txt line.
32
35
  def cookie_to_record(cookie)
33
36
  cookie.instance_eval {
34
37
  [
35
- @domain,
38
+ @httponly ? HTTPONLY_PREFIX + dot_domain : dot_domain,
36
39
  @for_domain ? True : False,
37
40
  @path,
38
41
  @secure ? True : False,
@@ -46,7 +49,15 @@ class HTTP::CookieJar::CookiestxtSaver < HTTP::CookieJar::AbstractSaver
46
49
  # Parses a line from cookies.txt and returns a cookie object if the
47
50
  # line represents a cookie record or returns nil otherwise.
48
51
  def parse_record(line)
49
- return nil if line.match(/^#/)
52
+ case line
53
+ when RE_HTTPONLY_PREFIX
54
+ httponly = true
55
+ line = $'
56
+ when /\A#/
57
+ return nil
58
+ else
59
+ httponly = false
60
+ end
50
61
 
51
62
  domain,
52
63
  s_for_domain, # Whether this cookie is for domain
@@ -68,6 +79,7 @@ class HTTP::CookieJar::CookiestxtSaver < HTTP::CookieJar::AbstractSaver
68
79
  :for_domain => s_for_domain == True,
69
80
  :path => path,
70
81
  :secure => s_secure == True,
82
+ :httponly => httponly,
71
83
  :expires => expires,
72
84
  :version => 0)
73
85
  end
@@ -9,11 +9,12 @@ end
9
9
  # :startdoc:
10
10
 
11
11
  class HTTP::CookieJar
12
+ # A store class that uses a hash of hashes.
12
13
  class HashStore < AbstractStore
13
- GC_THRESHOLD = HTTP::Cookie::MAX_COOKIES_TOTAL / 20
14
-
15
14
  def default_options
16
- {}
15
+ {
16
+ :gc_threshold => HTTP::Cookie::MAX_COOKIES_TOTAL / 20
17
+ }
17
18
  end
18
19
 
19
20
  def initialize(options = nil)
@@ -40,18 +41,20 @@ class HTTP::CookieJar
40
41
 
41
42
  def add(cookie)
42
43
  path_cookies = ((@jar[cookie.domain_name.hostname] ||= {})[cookie.path] ||= {})
44
+ path_cookies[cookie.name] = cookie
45
+ cleanup if (@gc_index += 1) >= @gc_threshold
46
+ self
47
+ end
43
48
 
44
- if cookie.expired?
45
- path_cookies.delete(cookie.name)
46
- else
47
- path_cookies[cookie.name] = cookie
48
- cleanup if (@gc_index += 1) >= GC_THRESHOLD
49
- end
50
-
49
+ def delete(cookie)
50
+ path_cookies = ((@jar[cookie.domain_name.hostname] ||= {})[cookie.path] ||= {})
51
+ path_cookies.delete(cookie.name)
51
52
  self
52
53
  end
54
+ private :delete
53
55
 
54
56
  def each(uri = nil)
57
+ now = Time.now
55
58
  if uri
56
59
  thost = DomainName.new(uri.host)
57
60
  tpath = uri.path
@@ -60,11 +63,13 @@ class HTTP::CookieJar
60
63
  paths.each { |path, hash|
61
64
  next unless HTTP::Cookie.path_match?(path, tpath)
62
65
  hash.delete_if { |name, cookie|
63
- if cookie.expired?
66
+ if cookie.expired?(now)
64
67
  true
65
68
  else
66
- cookie.accessed_at = Time.now
67
- yield cookie
69
+ if cookie.valid_for_uri?(uri)
70
+ cookie.accessed_at = now
71
+ yield cookie
72
+ end
68
73
  false
69
74
  end
70
75
  }
@@ -74,7 +79,7 @@ class HTTP::CookieJar
74
79
  @jar.each { |domain, paths|
75
80
  paths.each { |path, hash|
76
81
  hash.delete_if { |name, cookie|
77
- if cookie.expired?
82
+ if cookie.expired?(now)
78
83
  true
79
84
  else
80
85
  yield cookie
@@ -97,14 +102,14 @@ class HTTP::CookieJar
97
102
  end
98
103
 
99
104
  def cleanup(session = false)
105
+ now = Time.now
100
106
  all_cookies = []
101
-
102
107
  @jar.each { |domain, paths|
103
108
  domain_cookies = []
104
109
 
105
110
  paths.each { |path, hash|
106
111
  hash.delete_if { |name, cookie|
107
- if cookie.expired? || (session && cookie.session?)
112
+ if cookie.expired?(now) || (session && cookie.session?)
108
113
  true
109
114
  else
110
115
  domain_cookies << cookie
@@ -116,7 +121,7 @@ class HTTP::CookieJar
116
121
  if (debt = domain_cookies.size - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN) > 0
117
122
  domain_cookies.sort_by!(&:created_at)
118
123
  domain_cookies.slice!(0, debt).each { |cookie|
119
- add(cookie.expire!)
124
+ delete(cookie)
120
125
  }
121
126
  end
122
127
 
@@ -126,7 +131,7 @@ class HTTP::CookieJar
126
131
  if (debt = all_cookies.size - HTTP::Cookie::MAX_COOKIES_TOTAL) > 0
127
132
  all_cookies.sort_by!(&:created_at)
128
133
  all_cookies.slice!(0, debt).each { |cookie|
129
- add(cookie.expire!)
134
+ delete(cookie)
130
135
  }
131
136
  end
132
137
 
@@ -0,0 +1,327 @@
1
+ require 'http/cookie_jar'
2
+ require 'sqlite3'
3
+
4
+ class HTTP::CookieJar
5
+ class MozillaStore < AbstractStore
6
+ SCHEMA_VERSION = 5
7
+
8
+ def default_options
9
+ {
10
+ :gc_threshold => HTTP::Cookie::MAX_COOKIES_TOTAL / 20,
11
+ :app_id => 0,
12
+ :in_browser_element => false,
13
+ }
14
+ end
15
+
16
+ ALL_COLUMNS = %w[
17
+ baseDomain
18
+ appId inBrowserElement
19
+ name value
20
+ host path
21
+ expiry creationTime lastAccessed
22
+ isSecure isHttpOnly
23
+ ]
24
+ UK_COLUMNS = %w[
25
+ name host path
26
+ appId inBrowserElement
27
+ ]
28
+
29
+ def initialize(options = nil)
30
+ super
31
+
32
+ @filename = options[:filename] or raise ArgumentError, ':filename option is missing'
33
+
34
+ @db = SQLite3::Database.new(@filename)
35
+ @db.results_as_hash = true
36
+
37
+ upgrade_database
38
+
39
+ @gc_index = 0
40
+ end
41
+
42
+ def schema_version
43
+ @schema_version ||= @db.execute("PRAGMA user_version").first[0]
44
+ rescue SQLite3::SQLException
45
+ @logger.warn "couldn't get schema version!" if @logger
46
+ return nil
47
+ end
48
+
49
+ protected
50
+
51
+ def schema_version=(version)
52
+ @db.execute("PRAGMA user_version = %d" % version)
53
+ @schema_version = version
54
+ end
55
+
56
+ def create_table
57
+ self.schema_version = SCHEMA_VERSION
58
+ @db.execute("DROP TABLE IF EXISTS moz_cookies")
59
+ @db.execute(<<-'SQL')
60
+ CREATE TABLE moz_cookies (
61
+ id INTEGER PRIMARY KEY,
62
+ baseDomain TEXT,
63
+ appId INTEGER DEFAULT 0,
64
+ inBrowserElement INTEGER DEFAULT 0,
65
+ name TEXT,
66
+ value TEXT,
67
+ host TEXT,
68
+ path TEXT,
69
+ expiry INTEGER,
70
+ lastAccessed INTEGER,
71
+ creationTime INTEGER,
72
+ isSecure INTEGER,
73
+ isHttpOnly INTEGER,
74
+ CONSTRAINT moz_uniqueid UNIQUE (name, host, path, appId, inBrowserElement)
75
+ )
76
+ SQL
77
+ @db.execute(<<-'SQL')
78
+ CREATE INDEX moz_basedomain
79
+ ON moz_cookies (baseDomain,
80
+ appId,
81
+ inBrowserElement);
82
+ SQL
83
+ end
84
+
85
+ def upgrade_database
86
+ loop {
87
+ case schema_version
88
+ when nil, 0
89
+ self.schema_version = SCHEMA_VERSION
90
+ break
91
+ when 1
92
+ @db.execute("ALTER TABLE moz_cookies ADD lastAccessed INTEGER")
93
+ self.schema_version += 1
94
+ when 2
95
+ @db.execute("ALTER TABLE moz_cookies ADD baseDomain TEXT")
96
+
97
+ st_update = @db.prepare("UPDATE moz_cookies SET baseDomain = :baseDomain WHERE id = :id")
98
+
99
+ @db.execute("SELECT id, host FROM moz_cookies") { |row|
100
+ domain = DomainName.new(row[:host]).domain
101
+ st_update.execute(:baseDomain => domain, :id => row[:id])
102
+ }
103
+
104
+ @db.execute("CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)")
105
+ self.schema_version += 1
106
+ when 3
107
+ st_delete = @db.prepare("DELETE FROM moz_cookies WHERE id = :id")
108
+
109
+ prev_row = nil
110
+ @db.execute(<<-'SQL') { |row|
111
+ SELECT id, name, host, path FROM moz_cookies
112
+ ORDER BY name ASC, host ASC, path ASC, expiry ASC
113
+ SQL
114
+ if %w[name host path].all? { |col| row[col] == prev_row[col] }
115
+ st_delete.execute(prev_row['id'])
116
+ end
117
+ prev_row = row
118
+ }
119
+
120
+ @db.execute("ALTER TABLE moz_cookies ADD creationTime INTEGER")
121
+ @db.execute("UPDATE moz_cookies SET creationTime = (SELECT id WHERE id = moz_cookies.id)")
122
+ @db.execute("CREATE UNIQUE INDEX moz_uniqueid ON moz_cookies (name, host, path)")
123
+ self.schema_version += 1
124
+ when 4
125
+ @db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
126
+ @db.execute("DROP INDEX moz_basedomain")
127
+ create_table
128
+ @db.execute(<<-'SQL')
129
+ INSERT INTO moz_cookies
130
+ (baseDomain, appId, inBrowserElement, name, value, host, path, expiry,
131
+ lastAccessed, creationTime, isSecure, isHttpOnly)
132
+ SELECT baseDomain, 0, 0, name, value, host, path, expiry,
133
+ lastAccessed, creationTime, isSecure, isHttpOnly
134
+ FROM moz_cookies_old
135
+ SQL
136
+ @db.execute("DROP TABLE moz_cookies_old")
137
+ @logger.info("Upgraded database to schema version %d" % schema_version) if @logger
138
+ else
139
+ break
140
+ end
141
+ }
142
+
143
+ begin
144
+ @db.execute("SELECT %s from moz_cookies limit 1" % ALL_COLUMNS.join(', '))
145
+ rescue SQLite3::SQLException
146
+ create_table
147
+ end
148
+ end
149
+
150
+ public
151
+
152
+ def add(cookie)
153
+ @st_add ||=
154
+ @db.prepare('INSERT OR REPLACE INTO moz_cookies (%s) VALUES (%s)' % [
155
+ ALL_COLUMNS.join(', '),
156
+ ALL_COLUMNS.map { |col| ":#{col}" }.join(', ')
157
+ ])
158
+
159
+ @st_add.execute({
160
+ :baseDomain => cookie.domain_name.domain,
161
+ :appId => @app_id,
162
+ :inBrowserElement => @in_browser_element ? 1 : 0,
163
+ :name => cookie.name, :value => cookie.value,
164
+ :host => cookie.dot_domain,
165
+ :path => cookie.path,
166
+ :expiry => cookie.expires_at.to_i,
167
+ :creationTime => cookie.created_at.to_i,
168
+ :lastAccessed => cookie.accessed_at.to_i,
169
+ :isSecure => cookie.secure? ? 1 : 0,
170
+ :isHttpOnly => cookie.httponly? ? 1 : 0,
171
+ })
172
+ cleanup if (@gc_index += 1) >= @gc_threshold
173
+
174
+ self
175
+ end
176
+
177
+ def each(uri = nil)
178
+ now = Time.now
179
+ if uri
180
+ @st_cookies_for_domain ||=
181
+ @db.prepare(<<-'SQL')
182
+ SELECT * FROM moz_cookies
183
+ WHERE baseDomain = :baseDomain AND
184
+ appId = :appId AND
185
+ inBrowserElement = :inBrowserElement AND
186
+ expiry >= :expiry
187
+ SQL
188
+
189
+ @st_update_lastaccessed ||=
190
+ @db.prepare("UPDATE moz_cookies SET lastAccessed = :lastAccessed where id = :id")
191
+
192
+ thost = DomainName.new(uri.host)
193
+ tpath = HTTP::Cookie.normalize_path(uri.path)
194
+
195
+ @st_cookies_for_domain.execute({
196
+ :baseDomain => thost.domain_name.domain,
197
+ :appId => @app_id,
198
+ :inBrowserElement => @in_browser_element ? 1 : 0,
199
+ :expiry => now.to_i,
200
+ }).each { |row|
201
+ if secure = row['isSecure'] != 0
202
+ next unless URI::HTTPS === uri
203
+ end
204
+
205
+ cookie = HTTP::Cookie.new({}.tap { |attrs|
206
+ attrs[:name] = row['name']
207
+ attrs[:value] = row['value']
208
+ attrs[:domain] = row['host']
209
+ attrs[:path] = row['path']
210
+ attrs[:expires_at] = Time.at(row['expiry'])
211
+ attrs[:accessed_at] = Time.at(row['lastAccessed'])
212
+ attrs[:created_at] = Time.at(row['creationTime'])
213
+ attrs[:secure] = secure
214
+ attrs[:httponly] = row['isHttpOnly'] != 0
215
+ })
216
+
217
+ if cookie.valid_for_uri?(uri)
218
+ cookie.accessed_at = now
219
+ @st_update_lastaccessed.execute({
220
+ 'lastAccessed' => now.to_i,
221
+ 'id' => row['id'],
222
+ })
223
+ yield cookie
224
+ end
225
+ }
226
+ else
227
+ @st_all_cookies ||=
228
+ @db.prepare(<<-'SQL')
229
+ SELECT * FROM moz_cookies
230
+ WHERE appId = :appId AND
231
+ inBrowserElement = :inBrowserElement AND
232
+ expiry >= :expiry
233
+ SQL
234
+
235
+ @st_all_cookies.execute({
236
+ :appId => @app_id,
237
+ :inBrowserElement => @in_browser_element ? 1 : 0,
238
+ :expiry => now.to_i,
239
+ }).each { |row|
240
+ cookie = HTTP::Cookie.new({}.tap { |attrs|
241
+ attrs[:name] = row['name']
242
+ attrs[:value] = row['value']
243
+ attrs[:domain] = row['host']
244
+ attrs[:path] = row['path']
245
+ attrs[:expires_at] = Time.at(row['expiry'])
246
+ attrs[:accessed_at] = Time.at(row['lastAccessed'])
247
+ attrs[:created_at] = Time.at(row['creationTime'])
248
+ attrs[:secure] = row['isSecure'] != 0
249
+ attrs[:httponly] = row['isHttpOnly'] != 0
250
+ })
251
+
252
+ yield cookie
253
+ }
254
+ end
255
+ self
256
+ end
257
+
258
+ def clear
259
+ @db.execute("DELETE FROM moz_cookies")
260
+ self
261
+ end
262
+
263
+ def count
264
+ @st_count ||=
265
+ @db.prepare("SELECT COUNT(id) FROM moz_cookies")
266
+
267
+ @st_count.execute.first[0]
268
+ end
269
+ protected :count
270
+
271
+ def empty?
272
+ count == 0
273
+ end
274
+
275
+ def cleanup(session = false)
276
+ now = Time.now
277
+ all_cookies = []
278
+
279
+ @st_delete_expired ||=
280
+ @db.prepare("DELETE FROM moz_cookies WHERE expiry < :expiry")
281
+
282
+ @st_overusing_domains ||=
283
+ @db.prepare(<<-'SQL')
284
+ SELECT LTRIM(host, '.') domain, COUNT(*) count
285
+ FROM moz_cookies
286
+ GROUP BY domain
287
+ HAVING count > :count
288
+ SQL
289
+
290
+ @st_delete_per_domain_overuse ||=
291
+ @db.prepare(<<-'SQL')
292
+ DELETE FROM moz_cookies WHERE id IN (
293
+ SELECT id FROM moz_cookies
294
+ WHERE LTRIM(host, '.') = :domain
295
+ ORDER BY creationtime
296
+ LIMIT :limit)
297
+ SQL
298
+ @st_delete_total_overuse ||=
299
+ @db.prepare(<<-'SQL')
300
+ DELETE FROM moz_cookies WHERE id IN (
301
+ SELECT id FROM moz_cookies ORDER BY creationTime ASC LIMIT :limit
302
+ )
303
+ SQL
304
+
305
+ @st_delete_expired.execute({ 'expiry' => now.to_i })
306
+
307
+ @st_overusing_domains.execute({
308
+ 'count' => HTTP::Cookie::MAX_COOKIES_PER_DOMAIN
309
+ }).each { |row|
310
+ domain, count = row['domain'], row['count']
311
+
312
+ @st_delete_per_domain_overuse.execute({
313
+ 'domain' => domain,
314
+ 'limit' => count - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN,
315
+ })
316
+ }
317
+
318
+ overrun = count - HTTP::Cookie::MAX_COOKIES_TOTAL
319
+
320
+ if overrun > 0
321
+ @st_delete_total_overuse.execute({ 'limit' => overrun })
322
+ end
323
+
324
+ @gc_index = 0
325
+ end
326
+ end
327
+ end
@@ -162,6 +162,7 @@ class TestHTTPCookie < Test::Unit::TestCase
162
162
 
163
163
  assert_equal 'example.com', cookie.domain
164
164
  assert cookie.for_domain?
165
+ assert_equal '.example.com', cookie.dot_domain
165
166
  end
166
167
 
167
168
  def test_parse_domain_no_dot
@@ -173,6 +174,7 @@ class TestHTTPCookie < Test::Unit::TestCase
173
174
 
174
175
  assert_equal 'example.com', cookie.domain
175
176
  assert cookie.for_domain?
177
+ assert_equal '.example.com', cookie.dot_domain
176
178
  end
177
179
 
178
180
  def test_parse_domain_none
@@ -184,6 +186,7 @@ class TestHTTPCookie < Test::Unit::TestCase
184
186
 
185
187
  assert_equal 'example.com', cookie.domain
186
188
  assert !cookie.for_domain?
189
+ assert_equal 'example.com', cookie.dot_domain
187
190
  end
188
191
 
189
192
  def test_parse_max_age
@@ -360,20 +360,31 @@ class TestHTTPCookieJar < Test::Unit::TestCase
360
360
  :value => 'Foo#Baz',
361
361
  :path => '/foo/',
362
362
  :for_domain => false))
363
+ h_cookie = HTTP::Cookie.new(cookie_values(:name => 'Quux',
364
+ :value => 'Foo#Quux',
365
+ :httponly => true))
363
366
 
364
367
  @jar.add(cookie)
365
368
  @jar.add(s_cookie)
366
369
  @jar.add(cookie2)
370
+ @jar.add(h_cookie)
367
371
 
368
- assert_equal(3, @jar.cookies(url).length)
372
+ assert_equal(4, @jar.cookies(url).length)
369
373
 
370
374
  Dir.mktmpdir do |dir|
371
- @jar.save(File.join(dir, "cookies.txt"), :cookiestxt)
375
+ filename = File.join(dir, "cookies.txt")
376
+ @jar.save(filename, :cookiestxt)
377
+
378
+ content = File.read(filename)
379
+
380
+ assert_match(/^\.rubyforge\.org\t.*\tFoo\t/, content)
381
+ assert_match(/^rubyforge\.org\t.*\tBaz\t/, content)
382
+ assert_match(/^#HttpOnly_\.rubyforge\.org\t/, content)
372
383
 
373
384
  jar = HTTP::CookieJar.new
374
- jar.load(File.join(dir, "cookies.txt"), :cookiestxt) # HACK test the format
385
+ jar.load(filename, :cookiestxt) # HACK test the format
375
386
  cookies = jar.cookies(url)
376
- assert_equal(2, cookies.length)
387
+ assert_equal(3, cookies.length)
377
388
  cookies.each { |cookie|
378
389
  case cookie.name
379
390
  when 'Foo'
@@ -382,18 +393,27 @@ class TestHTTPCookieJar < Test::Unit::TestCase
382
393
  assert_equal 'rubyforge.org', cookie.domain
383
394
  assert_equal true, cookie.for_domain
384
395
  assert_equal '/', cookie.path
396
+ assert_equal false, cookie.httponly?
385
397
  when 'Baz'
386
398
  assert_equal 'Foo#Baz', cookie.value
387
399
  assert_equal 'rubyforge.org', cookie.domain
388
400
  assert_equal false, cookie.for_domain
389
401
  assert_equal '/foo/', cookie.path
402
+ assert_equal false, cookie.httponly?
403
+ when 'Quux'
404
+ assert_equal 'Foo#Quux', cookie.value
405
+ assert_equal expires, cookie.expires
406
+ assert_equal 'rubyforge.org', cookie.domain
407
+ assert_equal true, cookie.for_domain
408
+ assert_equal '/', cookie.path
409
+ assert_equal true, cookie.httponly?
390
410
  else
391
411
  raise
392
412
  end
393
413
  }
394
414
  end
395
415
 
396
- assert_equal(3, @jar.cookies(url).length)
416
+ assert_equal(4, @jar.cookies(url).length)
397
417
  end
398
418
 
399
419
  def test_expire_cookies
@@ -514,8 +534,7 @@ class TestHTTPCookieJar < Test::Unit::TestCase
514
534
  assert_equal('Foo1 Foo2', @jar.cookies(surl).map { |c| c.name }.sort.join(' ') )
515
535
  end
516
536
 
517
- def test_max_cookies
518
- jar = HTTP::CookieJar.new
537
+ def h_test_max_cookies(jar, slimit)
519
538
  limit_per_domain = HTTP::Cookie::MAX_COOKIES_PER_DOMAIN
520
539
  uri = URI('http://www.example.org/')
521
540
  date = Time.at(Time.now.to_i + 86400)
@@ -540,7 +559,6 @@ class TestHTTPCookieJar < Test::Unit::TestCase
540
559
  }.sort
541
560
 
542
561
  hlimit = HTTP::Cookie::MAX_COOKIES_TOTAL
543
- slimit = hlimit + HTTP::CookieJar::HashStore::GC_THRESHOLD
544
562
 
545
563
  n = hlimit / limit_per_domain * 2
546
564
 
@@ -569,4 +587,23 @@ class TestHTTPCookieJar < Test::Unit::TestCase
569
587
  cookie.domain == cookie.value
570
588
  }
571
589
  end
590
+
591
+ def test_max_cookies_hashstore
592
+ gc_threshold = 150
593
+ h_test_max_cookies(
594
+ HTTP::CookieJar.new(:hash,
595
+ :gc_threshold => gc_threshold),
596
+ HTTP::Cookie::MAX_COOKIES_TOTAL + gc_threshold)
597
+ end
598
+
599
+ def test_max_cookies_mozillastore
600
+ gc_threshold = 150
601
+ Dir.mktmpdir { |dir|
602
+ h_test_max_cookies(
603
+ HTTP::CookieJar.new(:mozilla,
604
+ :gc_threshold => gc_threshold,
605
+ :filename => File.join(dir, "cookies.sqlite")),
606
+ HTTP::Cookie::MAX_COOKIES_TOTAL + gc_threshold)
607
+ }
608
+ end
572
609
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http-cookie
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre2
4
+ version: 1.0.0.pre3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Akinori MUSHA
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2013-03-22 00:00:00.000000000 Z
14
+ date: 2013-03-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: domain_name
@@ -27,6 +27,20 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.5'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sqlite3
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: 1.3.3
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.3.3
30
44
  - !ruby/object:Gem::Dependency
31
45
  name: bundler
32
46
  requirement: !ruby/object:Gem::Requirement
@@ -125,6 +139,7 @@ files:
125
139
  - lib/http/cookie_jar/abstract_store.rb
126
140
  - lib/http/cookie_jar/cookiestxt_saver.rb
127
141
  - lib/http/cookie_jar/hash_store.rb
142
+ - lib/http/cookie_jar/mozilla_store.rb
128
143
  - lib/http/cookie_jar/yaml_saver.rb
129
144
  - test/helper.rb
130
145
  - test/simplecov_start.rb