cookie_store 0.1.4 → 0.2

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: 2fa62b0946bb98fb4646dd6d5a12cf0470ccca8c
4
- data.tar.gz: 7c60534b13a7e21151635f0985083edba439215f
2
+ SHA256:
3
+ metadata.gz: ed1b21def909112649960bb17b6e9f15291b27a45e1121111ba7fac8bc6944ca
4
+ data.tar.gz: 2c8066581ac182115e759ddf0421ce9e2a3ecc8c3bc6feab292efa9a2c9a3c16
5
5
  SHA512:
6
- metadata.gz: 4933dd902e5701f015ffc4f8b5c95ae869311505d3d3a054027c6aa31b96bb1b5d14751f751c2b6664e5c095faf1ae3912301b7640f5f18f70a20f59d1aa5385
7
- data.tar.gz: fec53203a8553011616023c165ca20217dad219cce3c713e22ab28f791034112aca8335502e77e66f7653ec8344b5ffa7afe6df77e6356da67f85e29ad1c0956
6
+ metadata.gz: 8db6b08273b5324d8866709e52af11eefe89538c891cf5d551160a51df4386a612defb0e8f560e55d406fcbbf15add61b415b56ffb2c933877d66e7ee557589d
7
+ data.tar.gz: 1049c26606be9fe1585377c983357958416bd842a4e36c41cac7107f8f58841fadd003e29cf2e98cef5ff6f1d67078f0af9461b58783a7f0f0e15632b4d6c63e
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ stream_parser:
11
+ name: CookieStore Test
12
+ runs-on: ubuntu-20.04
13
+
14
+ steps:
15
+ - uses: ruby/setup-ruby@v1
16
+ with:
17
+ ruby-version: 3.0
18
+
19
+ - uses: actions/checkout@v2
20
+
21
+ - run: bundle
22
+
23
+ - run: bundle exec rake test
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ *.gem
3
+ .byebug_history
4
+ Gemfile.lock
5
+ coverage/
data/.tm_properties ADDED
@@ -0,0 +1 @@
1
+ exclude = '{$exclude,log,tmp,.tm_properties,coverage}'
data/cookie_store.gemspec CHANGED
@@ -1,9 +1,8 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
1
+ require_relative 'lib/cookie_store/version'
3
2
 
4
3
  Gem::Specification.new do |s|
5
4
  s.name = "cookie_store"
6
- s.version = '0.1.4'
5
+ s.version = CookieStore::VERSION
7
6
  s.authors = ["Jon Bracy"]
8
7
  s.email = ["jonbracy@gmail.com"]
9
8
  s.homepage = "https://github.com/malomalo/cookie_store"
@@ -14,8 +13,11 @@ Gem::Specification.new do |s|
14
13
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
14
  s.require_paths = ["lib"]
16
15
 
16
+ s.add_runtime_dependency 'stream_parser', '>= 0.2'
17
+
17
18
  # Developoment
18
19
  s.add_development_dependency 'rake'
20
+ s.add_development_dependency 'byebug'
19
21
  # s.add_development_dependency 'rdoc'
20
22
  # s.add_development_dependency 'sdoc'
21
23
  s.add_development_dependency 'minitest'
@@ -24,4 +26,5 @@ Gem::Specification.new do |s|
24
26
  s.add_development_dependency 'faker'
25
27
  s.add_development_dependency 'webmock'
26
28
  s.add_development_dependency 'activesupport'
29
+ s.add_development_dependency 'simplecov'
27
30
  end
data/lib/cookie_store.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'uri'
2
2
 
3
3
  class CookieStore
4
+
5
+ autoload :CookieParser, 'cookie_store/cookie_parser'
4
6
 
5
7
  # Maximum number of bytes per cookie (RFC 6265 6.1 requires at least 4096)
6
8
  MAX_COOKIE_LENGTH = 4096
@@ -15,14 +17,14 @@ class CookieStore
15
17
  def set_cookie(request_uri, set_cookie_value)
16
18
  request_uri = URI.parse(request_uri)
17
19
 
18
- CookieStore::Cookie.parse_cookies(request_uri, set_cookie_value).each do |cookie|
20
+ CookieStore::Cookie.parse_cookies(request_uri, set_cookie_value) do |cookie|
19
21
  # reject as per RFC2965 Section 3.3.2
20
22
  return if !cookie.request_match?(request_uri) || !(cookie.domain =~ /.+\..+/ || cookie.domain == 'localhost')
21
23
 
22
24
  # reject cookies over the max-bytes
23
25
  return if cookie.to_s.size > MAX_COOKIE_LENGTH
24
26
 
25
- add(cookie)
27
+ add(cookie)
26
28
  end
27
29
  end
28
30
 
@@ -1,37 +1,7 @@
1
1
  class CookieStore::Cookie
2
2
 
3
- QUOTED_PAIR = "\\\\[\\x00-\\x7F]"
4
- LWS = "\\r\\n(?:[ \\t]+)"
5
- QDTEXT = "[\\t\\x20-\\x21\\x23-\\x3A\\x3C-\\x7E\\x80-\\xFF]|(?:#{LWS})"
6
- QUOTED_TEXT = "(?:#{QUOTED_PAIR}|#{QDTEXT})*"
7
- IPADDR = /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/
8
-
9
- TOKEN = '[^(),\/<>@;:\\\"\[\]?={}\s]+'
10
- VALUE = "(?:#{TOKEN}|#{IPADDR}|[^,;\\s]+)"
11
- EXPIRES_AT_VALUE = '[A-Za-z]{3},\ \d{2}[-\ ][A-Za-z]{3}[-\ ]\d{4}\ \d{2}:\d{2}:\d{2}\ (?:[A-Z]{3}|[-+]\d{4})'
12
- NUMERICAL_TIMEZONE = /[-+]\d{4}$/
13
-
14
-
15
- COOKIE = /(?<name>#{TOKEN})=(?:"(?<quoted_value>#{QUOTED_TEXT})"|(?<value>#{VALUE}))(?<attributes>.*)/n
16
- COOKIE_AV = %r{
17
- ;\s+
18
- (?<key>#{TOKEN})
19
- (?:
20
- =
21
- (?:
22
- "(?<quoted_value>#{QUOTED_TEXT})"
23
- |
24
- (?<value>#{EXPIRES_AT_VALUE}|#{VALUE})
25
- )
26
- ){0,1}
27
- }nx
28
- COOKIES = %r{
29
- #{TOKEN}=(?:"#{QUOTED_TEXT}"|#{VALUE})
30
- (?:;\s+#{TOKEN}(?:=(?:"#{QUOTED_TEXT}"|(?:#{EXPIRES_AT_VALUE}|#{VALUE}))){0,1})*
31
- }nx
32
-
3
+ IPADDR = /\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/
33
4
 
34
-
35
5
  # [String] The name of the cookie.
36
6
  attr_reader :name
37
7
 
@@ -87,7 +57,7 @@ class CookieStore::Cookie
87
57
  # [Time] Time when this cookie was first evaluated and created.
88
58
  attr_reader :created_at
89
59
 
90
- def initialize(name, value, options={})
60
+ def initialize(name, value, attributes={})
91
61
  @name = name
92
62
  @value = value
93
63
  @secure = false
@@ -96,8 +66,12 @@ class CookieStore::Cookie
96
66
  @discard = false
97
67
  @created_at = Time.now
98
68
 
99
- options.each do |attr_name, attr_value|
100
- self.instance_variable_set(:"@#{attr_name}", attr_value)
69
+ @attributes = attributes
70
+
71
+ %i{name value domain path secure http_only version comment comment_url discard ports expires max_age created_at}.each do |attr_name|
72
+ if attributes.has_key?(attr_name)
73
+ self.instance_variable_set(:"@#{attr_name}", attributes[attr_name])
74
+ end
101
75
  end
102
76
  end
103
77
 
@@ -186,70 +160,28 @@ class CookieStore::Cookie
186
160
  ports.include?(request_port)
187
161
  end
188
162
 
189
- def self.parse_cookies(request_uri, set_cookie_value)
190
- uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
191
- cookies = []
192
- set_cookie_value.scan(COOKIES) do |cookie|
193
- cookies << parse(uri, cookie)
194
- end
195
- cookies
163
+ def self.parse(request_uri, set_cookie_value)
164
+ parse_cookies(request_uri, set_cookie_value).first
196
165
  end
197
166
 
198
- def self.parse(request_uri, set_cookie_value)
167
+ def self.parse_cookies(request_uri, set_cookie_value)
199
168
  uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
200
- data = COOKIE.match(set_cookie_value)
201
- options = {}
202
-
203
- if !data
204
- raise Net::HTTPHeaderSyntaxError.new("Invalid Set-Cookie header format")
205
- end
206
169
 
207
- if data[:attributes]
208
- data[:attributes].scan(COOKIE_AV) do |key, quoted_value, value|
209
- value = quoted_value.gsub(/\\(.)/, '\1') if !value && quoted_value
170
+ cookies = []
171
+ CookieStore::CookieParser.parse(set_cookie_value) do |parsed|
172
+ parsed[:attributes][:domain] ||= uri.host.downcase
173
+ parsed[:attributes][:path] ||= uri.path
174
+
175
+ cookie = CookieStore::Cookie.new(parsed[:key], parsed[:value], parsed[:attributes])
210
176
 
211
- # RFC 2109 4.1, Attributes (names) are case-insensitive
212
- case key.downcase
213
- when 'comment'
214
- options[:comment] = value
215
- when 'commenturl'
216
- options[:comment_url] = value
217
- when 'discard'
218
- options[:discard] = true
219
- when 'domain'
220
- if value =~ IPADDR
221
- options[:domain] = value
222
- else
223
- # As per RFC2965 if a host name contains no dots, the effective host name is
224
- # that name with the string .local appended to it.
225
- value = "#{value}.local" if !value.include?('.')
226
- options[:domain] = (value.start_with?('.') ? value : ".#{value}").downcase
227
- end
228
- when 'expires'
229
- if value.include?('-') && !value.match(NUMERICAL_TIMEZONE)
230
- options[:expires] = DateTime.strptime(value, '%a, %d-%b-%Y %H:%M:%S %Z')
231
- else
232
- options[:expires] = DateTime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z')
233
- end
234
- when 'max-age'
235
- options[:max_age] = value.to_i
236
- when 'path'
237
- options[:path] = value
238
- when 'port'
239
- options[:ports] = value.split(',').map(&:to_i)
240
- when 'secure'
241
- options[:secure] = true
242
- when 'httponly'
243
- options[:http_only] = true
244
- when 'version'
245
- options[:version] = value.to_i
246
- end
177
+ cookies << if block_given?
178
+ yield(cookie)
179
+ else
180
+ cookie
247
181
  end
248
182
  end
249
- options[:domain] ||= uri.host.downcase
250
- options[:path] ||= uri.path
251
-
252
- CookieStore::Cookie.new(data[:name], data[:value] || data[:quoted_value].gsub(/\\(.)/, '\1'), options)
183
+
184
+ cookies
253
185
  end
254
186
 
255
187
  end
@@ -0,0 +1,110 @@
1
+ require 'stream_parser'
2
+
3
+ class CookieStore::CookieParser
4
+
5
+ include StreamParser
6
+
7
+ NUMERICAL_TIMEZONE = /[-+]\d{4}\Z/
8
+
9
+ def parse
10
+ cookie = {attributes: {}}
11
+
12
+ @stack = [:cookie_name]
13
+ while !eos?
14
+ case @stack.last
15
+ when :cookie_name
16
+ scan_until(/\s*=\s*/)
17
+ if match == '='
18
+ @stack << :cookie_value
19
+ cookie[:key] = pre_match
20
+ end
21
+ when :cookie_value
22
+ scan_until(/\s*(['";]\s*|\Z)/)
23
+ if match.strip == '"' || match.strip == "'"
24
+ cookie[:value] = quoted_value(match.strip)
25
+ @stack.pop
26
+ @stack << :cookie_attributes
27
+ elsif match
28
+ cookie[:value] = pre_match
29
+ @stack.pop
30
+ @stack << :cookie_attributes
31
+ end
32
+ when :cookie_attributes
33
+ # RFC 2109 4.1, Attributes (names) are case-insensitive
34
+ scan_until(/[,=;]\s*/)
35
+ if match&.start_with?('=')
36
+ key = normalize_key(pre_match)
37
+ scan_until(key == :expires ? /\s*((?<!\w{3}),|['";])\s*/ : /\s*(['";,]\s*|\Z)/)
38
+ if match =~ /["']\s*\Z/
39
+ cookie[:attributes][key] = normalize_attribute_value(key, quoted_value(match.strip))
40
+ elsif match =~ /,\s*\Z/
41
+ cookie[:attributes][key] = normalize_attribute_value(key, pre_match)
42
+ yield(cookie)
43
+ cookie = {attributes: {}}
44
+ @stack.pop
45
+ else
46
+ cookie[:attributes][key] = normalize_attribute_value(key, pre_match)
47
+ end
48
+ elsif match&.start_with?(',')
49
+ yield(cookie)
50
+ cookie = {attributes: {}}
51
+ @stack.pop
52
+ else
53
+ cookie[:attributes][normalize_key(pre_match)] = true
54
+ end
55
+ end
56
+ end
57
+
58
+ yield(cookie)
59
+ end
60
+
61
+ def normalize_key(key)
62
+ key = key.downcase.gsub('-','_')
63
+ if key == 'port'
64
+ :ports
65
+ elsif key == 'httponly'
66
+ :http_only
67
+ elsif key == 'commenturl'
68
+ :comment_url
69
+ else
70
+ key.to_sym
71
+ end
72
+ end
73
+
74
+ def normalize_attribute_value(key, value)
75
+ case key
76
+ when :domain
77
+ if value =~ CookieStore::Cookie::IPADDR
78
+ value
79
+ else
80
+ # As per RFC2965 if a host name contains no dots, the effective host
81
+ # name is that name with the string .local appended to it.
82
+ value = "#{value}.local" if !value.include?('.')
83
+ (value.start_with?('.') ? value : ".#{value}").downcase
84
+ end
85
+ when :expires
86
+ byebug if $debug
87
+ case value
88
+ when /\w{3}, \d{2}-\w{3}-\d{2} /
89
+ DateTime.strptime(value, '%a, %d-%b-%y %H:%M:%S %Z')
90
+ when /\w{3}, \d{2}-\w{3}-\d{4} /
91
+ DateTime.strptime(value, '%a, %d-%b-%Y %H:%M:%S %Z')
92
+ when /\w{3}, \d{2} \w{3} \d{2} /
93
+ DateTime.strptime(value, '%a, %d %b %y %H:%M:%S %Z')
94
+ when /\w{3}, \d{2} \w{3} \d{4} /
95
+ DateTime.strptime(value, '%a, %d %b %Y %H:%M:%S %Z')
96
+ else
97
+ DateTime.parse(value)
98
+ end
99
+ when :max_age
100
+ value&.to_i
101
+ when :ports
102
+ value.split(',').map(&:to_i)
103
+ when :version
104
+ value.to_i
105
+ else
106
+ value
107
+ end
108
+ end
109
+
110
+ end
@@ -0,0 +1,3 @@
1
+ class CookieStore
2
+ VERSION = '0.2'
3
+ end
@@ -13,7 +13,7 @@ class CookieStore::CookieTest < Minitest::Test
13
13
 
14
14
  test "::new(name, value, options)" do
15
15
  #TODO: test all options are set
16
- cookie = CookieStore::Cookie.new('foo', 'bar', :domain => 'test.com')
16
+ cookie = CookieStore::Cookie.new('foo', 'bar', domain: 'test.com')
17
17
 
18
18
  assert_equal 'test.com', cookie.domain
19
19
  end
@@ -27,7 +27,7 @@ class CookieStore::CookieTest < Minitest::Test
27
27
  '123.456.57.21' => '123.456.57.21'
28
28
  #TODO: not sure how ipv6 works '[E3D7::51F4:9BC8:C0A8:6420]' => '[E3D7::51F4:9BC8:C0A8:6420]'
29
29
  }.each do |host, cookie_host|
30
- cookie = CookieStore::Cookie.new('key', 'value', :domain => cookie_host)
30
+ cookie = CookieStore::Cookie.new('key', 'value', domain: cookie_host)
31
31
  assert_equal true, cookie.domain_match(host)
32
32
  end
33
33
 
@@ -43,7 +43,7 @@ class CookieStore::CookieTest < Minitest::Test
43
43
  '123.456.57.21' => '.123.456.57.21'
44
44
  #TODO: not sure how ipv6 works '[E3D7::51F4:9BC8:C0A8:6420]' => '[E3D7::51F4:9BC8:C0A8:6421]'
45
45
  }.each do |host, cookie_host|
46
- cookie = CookieStore::Cookie.new('key', 'value', :domain => cookie_host)
46
+ cookie = CookieStore::Cookie.new('key', 'value', domain: cookie_host)
47
47
  assert_equal false, cookie.domain_match(host)
48
48
  end
49
49
  end
@@ -55,7 +55,7 @@ class CookieStore::CookieTest < Minitest::Test
55
55
  '/test' => '/',
56
56
  '/this/is/my/url' => '/this/is'
57
57
  }.each do |path, cookie_path|
58
- cookie = CookieStore::Cookie.new('key', 'value', :path => cookie_path)
58
+ cookie = CookieStore::Cookie.new('key', 'value', path: cookie_path)
59
59
  assert_equal true, cookie.path_match(path)
60
60
  end
61
61
 
@@ -63,7 +63,7 @@ class CookieStore::CookieTest < Minitest::Test
63
63
  '/test' => '/rest',
64
64
  '/' => '/test'
65
65
  }.each do |path, cookie_path|
66
- cookie = CookieStore::Cookie.new('key', 'value', :path => cookie_path)
66
+ cookie = CookieStore::Cookie.new('key', 'value', path: cookie_path)
67
67
  assert_equal false, cookie.path_match(path)
68
68
  end
69
69
  end
@@ -76,7 +76,7 @@ class CookieStore::CookieTest < Minitest::Test
76
76
  end
77
77
 
78
78
  test "::port_match(request_port) with ports attribute set" do
79
- cookie = CookieStore::Cookie.new('key', 'value', :ports => [80, 8700])
79
+ cookie = CookieStore::Cookie.new('key', 'value', ports: [80, 8700])
80
80
  assert_equal true, cookie.port_match(8700)
81
81
  assert_equal false, cookie.port_match(87)
82
82
  end
@@ -97,14 +97,19 @@ class CookieStore::CookieTest < Minitest::Test
97
97
 
98
98
  test "#expires_at perfers max-age to expires" do
99
99
  travel_to Time.new(2013, 12, 13, 8, 26, 12, 0) do
100
- cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age=3600 Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
100
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age=3600; Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
101
101
  assert_equal Time.new(2013, 12, 13, 9, 26, 12, 0), cookie.expires_at
102
102
  end
103
103
  end
104
104
 
105
105
  test "#expires_at returns nil if no max-age or expires attribute" do
106
106
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar')
107
- assert_equal nil, cookie.expires_at
107
+ assert_nil cookie.expires_at
108
+ end
109
+
110
+ test "date formats" do
111
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foor=bar; expires=Fri, 04-Jun-21 14:13:58 GMT; path=/;')
112
+ assert_equal DateTime.new(2021, 6, 04, 14, 13, 58, 0), cookie.expires_at
108
113
  end
109
114
 
110
115
  # CookieStore::Cookie.expired? =========================================================
@@ -188,13 +193,13 @@ class CookieStore::CookieTest < Minitest::Test
188
193
  assert_equal '/test', cookie.path
189
194
  assert_equal false, cookie.secure
190
195
  assert_equal false, cookie.http_only
191
- assert_equal nil, cookie.comment
192
- assert_equal nil, cookie.comment_url
196
+ assert_nil cookie.comment
197
+ assert_nil cookie.comment_url
193
198
  assert_equal 1, cookie.version
194
199
  assert_equal false, cookie.discard
195
- assert_equal nil, cookie.ports
196
- assert_equal nil, cookie.expires
197
- assert_equal nil, cookie.max_age
200
+ assert_nil cookie.ports
201
+ assert_nil cookie.expires
202
+ assert_nil cookie.max_age
198
203
  end
199
204
 
200
205
  test "::parse a cookie with options" do
@@ -206,13 +211,13 @@ class CookieStore::CookieTest < Minitest::Test
206
211
  assert_equal '/', cookie.path
207
212
  assert_equal false, cookie.secure
208
213
  assert_equal true, cookie.http_only
209
- assert_equal nil, cookie.comment
210
- assert_equal nil, cookie.comment_url
214
+ assert_nil cookie.comment
215
+ assert_nil cookie.comment_url
211
216
  assert_equal 1, cookie.version
212
217
  assert_equal false, cookie.discard
213
- assert_equal nil, cookie.ports
214
- assert_equal nil, cookie.expires
215
- assert_equal nil, cookie.max_age
218
+ assert_nil cookie.ports
219
+ assert_nil cookie.expires
220
+ assert_nil cookie.max_age
216
221
  end
217
222
 
218
223
  test "::parse normalizes the request domain" do
@@ -234,9 +239,9 @@ class CookieStore::CookieTest < Minitest::Test
234
239
  test "::parse a simple quoted cookie" do
235
240
  cookie = CookieStore::Cookie.parse('http://google.com/test', 'foo="b\"ar"')
236
241
 
237
- assert_equal 'google.com', cookie.domain
238
- assert_equal 'foo', cookie.name
239
- assert_equal 'b"ar', cookie.value
242
+ assert_equal 'google.com', cookie.domain
243
+ assert_equal 'foo', cookie.name
244
+ assert_equal 'b"ar', cookie.value
240
245
  end
241
246
 
242
247
  test "::parse domain attribute without leading ." do
@@ -312,6 +317,19 @@ class CookieStore::CookieTest < Minitest::Test
312
317
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 GMT"')
313
318
  assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
314
319
 
320
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 2021 22:23:01 GMT'")
321
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
322
+
323
+ # Wed, 13 Jan 21 22:23:01 GMT format
324
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 21 22:23:01 GMT')
325
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
326
+
327
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 21 22:23:01 GMT"')
328
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
329
+
330
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 21 22:23:01 GMT'")
331
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
332
+
315
333
  # Wed, 13-Jan-2021 22:23:01 GMT format
316
334
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13-Jan-2021 22:23:01 GMT')
317
335
  assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
@@ -319,12 +337,38 @@ class CookieStore::CookieTest < Minitest::Test
319
337
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13-Jan-2021 22:23:01 GMT"')
320
338
  assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
321
339
 
340
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13-Jan-2021 22:23:01 GMT'")
341
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
342
+
343
+ # Wed, 13-Jan-21 22:23:01 GMT format
344
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13-Jan-21 22:23:01 GMT')
345
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
346
+
347
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13-Jan-21 22:23:01 GMT"')
348
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
349
+
350
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13-Jan-21 22:23:01 GMT'")
351
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
352
+
322
353
  # Wed, 13 Jan 2021 22:23:01 -0000 format
323
354
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 2021 22:23:01 -0000')
324
355
  assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
325
356
 
326
357
  cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 2021 22:23:01 +0000"')
327
358
  assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
359
+
360
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 2021 22:23:01 +0000'")
361
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
362
+
363
+ # Wed, 13 Jan 21 22:23:01 -0000 format
364
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires=Wed, 13 Jan 21 22:23:01 -0000')
365
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
366
+
367
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Expires="Wed, 13 Jan 21 22:23:01 +0000"')
368
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
369
+
370
+ cookie = CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Expires='Wed, 13 Jan 21 22:23:01 +0000'")
371
+ assert_equal DateTime.new(2021, 1, 13, 22, 23, 1, 0), cookie.expires
328
372
  end
329
373
 
330
374
  test "::parse max_age attribute" do
@@ -354,7 +398,15 @@ class CookieStore::CookieTest < Minitest::Test
354
398
  assert_equal true, cookies[1].http_only
355
399
  end
356
400
 
357
- # TODO: test expires_at, based on expires attribute
358
- # TODO: test expires_at, based on max-age attribute
401
+ # CookieStore::Cookie parse invalid cookies =========================================================
402
+ test "unclosed quotes" do
403
+ assert_raises Net::HTTPHeaderSyntaxError do
404
+ CookieStore::Cookie.parse('http://google.com/test/this', 'foo=bar; Max-Age="3660')
405
+ end
406
+
407
+ assert_raises Net::HTTPHeaderSyntaxError do
408
+ CookieStore::Cookie.parse('http://google.com/test/this', "foo=bar; Max-Age='3660")
409
+ end
410
+ end
359
411
 
360
412
  end
data/test/test_helper.rb CHANGED
@@ -6,6 +6,9 @@ lib = File.expand_path(File.join(root, 'lib'))
6
6
 
7
7
  $LOAD_PATH << lib
8
8
 
9
+ require 'simplecov'
10
+ SimpleCov.start
11
+
9
12
  require 'cookie_store'
10
13
  require "minitest/autorun"
11
14
  require 'minitest/unit'
@@ -13,12 +16,18 @@ require 'minitest/reporters'
13
16
  require 'faker'
14
17
  require 'webmock/minitest'
15
18
  require "mocha"
16
- require "mocha/mini_test"
19
+ require "mocha/minitest"
17
20
  require 'active_support/time'
18
21
  require 'active_support/testing/time_helpers'
22
+ require "byebug"
19
23
 
20
24
  Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
21
25
 
26
+
27
+
28
+
29
+ $debug = false
30
+
22
31
  # File 'lib/active_support/testing/declarative.rb', somewhere in rails....
23
32
  class Minitest::Test
24
33
  include ActiveSupport::Testing::TimeHelpers
@@ -36,4 +45,12 @@ class Minitest::Test
36
45
  end
37
46
  end
38
47
 
48
+ def debug
49
+ $debug = true
50
+ puts '=========================='
51
+ yield
52
+ ensure
53
+ puts '=========================='
54
+ $debug = false
55
+ end
39
56
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cookie_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-30 00:00:00.000000000 Z
11
+ date: 2021-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: stream_parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rake
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: minitest
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +136,20 @@ dependencies:
108
136
  - - ">="
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
111
153
  description: A Ruby library to handle client-side HTTP cookies
112
154
  email:
113
155
  - jonbracy@gmail.com
@@ -115,15 +157,19 @@ executables: []
115
157
  extensions: []
116
158
  extra_rdoc_files: []
117
159
  files:
160
+ - ".github/workflows/ci.yml"
161
+ - ".gitignore"
162
+ - ".tm_properties"
118
163
  - Gemfile
119
- - Gemfile.lock
120
164
  - LICENSE
121
165
  - README.md
122
166
  - Rakefile
123
167
  - cookie_store.gemspec
124
168
  - lib/cookie_store.rb
125
169
  - lib/cookie_store/cookie.rb
170
+ - lib/cookie_store/cookie_parser.rb
126
171
  - lib/cookie_store/hash_store.rb
172
+ - lib/cookie_store/version.rb
127
173
  - test/cookie_store/cookie_test.rb
128
174
  - test/cookie_store/hash_store_test.rb
129
175
  - test/cookie_store_test.rb
@@ -131,7 +177,7 @@ files:
131
177
  homepage: https://github.com/malomalo/cookie_store
132
178
  licenses: []
133
179
  metadata: {}
134
- post_install_message:
180
+ post_install_message:
135
181
  rdoc_options: []
136
182
  require_paths:
137
183
  - lib
@@ -146,9 +192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
192
  - !ruby/object:Gem::Version
147
193
  version: '0'
148
194
  requirements: []
149
- rubyforge_project:
150
- rubygems_version: 2.4.5
151
- signing_key:
195
+ rubygems_version: 3.2.3
196
+ signing_key:
152
197
  specification_version: 4
153
198
  summary: A Ruby library to handle client-side HTTP cookies
154
199
  test_files:
data/Gemfile.lock DELETED
@@ -1,57 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- cookie_store (0.1.4)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- activesupport (4.1.8)
10
- i18n (~> 0.6, >= 0.6.9)
11
- json (~> 1.7, >= 1.7.7)
12
- minitest (~> 5.1)
13
- thread_safe (~> 0.1)
14
- tzinfo (~> 1.1)
15
- addressable (2.3.6)
16
- ansi (1.4.3)
17
- builder (3.2.2)
18
- crack (0.4.2)
19
- safe_yaml (~> 1.0.0)
20
- faker (1.4.3)
21
- i18n (~> 0.5)
22
- i18n (0.6.11)
23
- json (1.8.1)
24
- metaclass (0.0.4)
25
- minitest (5.5.0)
26
- minitest-reporters (1.0.8)
27
- ansi
28
- builder
29
- minitest (>= 5.0)
30
- ruby-progressbar
31
- mocha (1.1.0)
32
- metaclass (~> 0.0.1)
33
- rake (10.4.2)
34
- ruby-progressbar (1.7.0)
35
- safe_yaml (1.0.4)
36
- thread_safe (0.3.4)
37
- tzinfo (1.2.2)
38
- thread_safe (~> 0.1)
39
- webmock (1.20.4)
40
- addressable (>= 2.3.6)
41
- crack (>= 0.3.2)
42
-
43
- PLATFORMS
44
- ruby
45
-
46
- DEPENDENCIES
47
- activesupport
48
- cookie_store!
49
- faker
50
- minitest
51
- minitest-reporters
52
- mocha
53
- rake
54
- webmock
55
-
56
- BUNDLED WITH
57
- 1.10.4