Class: CookieStore::Cookie

Inherits:
Object
  • Object
show all
Defined in:
lib/cookie_store/cookie.rb

Constant Summary collapse

IPADDR =
/\A#{URI::REGEXP::PATTERN::IPV4ADDR}\Z|\A#{URI::REGEXP::PATTERN::IPV6ADDR}\Z/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, value, attributes = {}) ⇒ Cookie

Returns a new instance of Cookie.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/cookie_store/cookie.rb', line 60

def initialize(name, value, attributes={})
  @name = name
  @value = value
  @secure = false
  @http_only = false
  @version = 1
  @discard = false
  @created_at = Time.now
  
  @attributes = attributes

  %i{name value domain path secure http_only version comment comment_url discard ports expires max_age created_at}.each do |attr_name|
    if attributes.has_key?(attr_name)
      self.instance_variable_set(:"@#{attr_name}", attributes[attr_name])
    end
  end
end

Instance Attribute Details

#commentObject (readonly)

String, nil

RFC 2965 field for indicating comment (or a location)

describing the cookie to a usesr agent.



38
39
40
# File 'lib/cookie_store/cookie.rb', line 38

def comment
  @comment
end

#comment_urlObject (readonly)

String, nil

RFC 2965 field for indicating comment (or a location)

describing the cookie to a usesr agent.



38
39
40
# File 'lib/cookie_store/cookie.rb', line 38

def comment_url
  @comment_url
end

#created_atObject (readonly)

Time

Time when this cookie was first evaluated and created.



58
59
60
# File 'lib/cookie_store/cookie.rb', line 58

def created_at
  @created_at
end

#discardObject (readonly)

Boolean

RFC 2965 field for indicating session lifetime for a cookie



41
42
43
# File 'lib/cookie_store/cookie.rb', line 41

def discard
  @discard
end

#domainObject (readonly)

String

The domain scope of the cookie. Follows the RFC 2965

‘effective host’ rules. A ‘dot’ prefix indicates that it applies both to the non-dotted domain and child domains, while no prefix indicates that only exact matches of the domain are in scope.



15
16
17
# File 'lib/cookie_store/cookie.rb', line 15

def domain
  @domain
end

#expiresObject (readonly)

DateTime

The Expires directive tells the browser when to delete the cookie.

Derived from the format used in RFC 1123



50
51
52
# File 'lib/cookie_store/cookie.rb', line 50

def expires
  @expires
end

#http_onlyObject (readonly)

Boolean

Popular browser extension to mark a cookie as invisible

to code running within the browser, such as JavaScript



29
30
31
# File 'lib/cookie_store/cookie.rb', line 29

def http_only
  @http_only
end

#max_ageObject (readonly)

Fixnum

RFC 6265 allows the use of the Max-Age attribute to set the

cookie’s expiration as an interval of seconds in the future, relative to the time the browser received the cookie.



55
56
57
# File 'lib/cookie_store/cookie.rb', line 55

def max_age
  @max_age
end

#nameObject (readonly)

String

The name of the cookie.



6
7
8
# File 'lib/cookie_store/cookie.rb', line 6

def name
  @name
end

#pathObject (readonly)

String

The path scope of the cookie. The cookie applies to URI paths

that prefix match this value.



19
20
21
# File 'lib/cookie_store/cookie.rb', line 19

def path
  @path
end

#portsObject (readonly)

Array<FixNum>, nil

RFC 2965 port scope for the cookie. If not nil,

indicates specific ports on the HTTP server which should receive this cookie if contacted.



46
47
48
# File 'lib/cookie_store/cookie.rb', line 46

def ports
  @ports
end

#secureObject (readonly)

Boolean

The secure flag is set to indicate that the cookie should

only be sent securely. Nearly all HTTP User Agent implementations assume this to mean that the cookie should only be sent over a SSL/TLS-protected connection



25
26
27
# File 'lib/cookie_store/cookie.rb', line 25

def secure
  @secure
end

#valueObject (readonly)

String

The value of the cookie, without any attempts at decoding.



9
10
11
# File 'lib/cookie_store/cookie.rb', line 9

def value
  @value
end

#versionObject (readonly)

Fixnum

Version indicator, currently either

  • 0 for netscape cookies

  • 1 for RFC 2965 cookies



34
35
36
# File 'lib/cookie_store/cookie.rb', line 34

def version
  @version
end

Class Method Details

.parse(request_uri, set_cookie_value) ⇒ Object



163
164
165
# File 'lib/cookie_store/cookie.rb', line 163

def self.parse(request_uri, set_cookie_value)
  parse_cookies(request_uri, set_cookie_value).first
end

.parse_cookies(request_uri, set_cookie_value) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/cookie_store/cookie.rb', line 167

def self.parse_cookies(request_uri, set_cookie_value)
  uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
  
  cookies = []
  CookieStore::CookieParser.parse(set_cookie_value) do |parsed|
    parsed[:attributes][:domain]  ||= uri.host.downcase
    parsed[:attributes][:path]    ||= uri.path

    cookie = CookieStore::Cookie.new(parsed[:key], parsed[:value], parsed[:attributes])

    cookies << if block_given?
      yield(cookie)
    else
      cookie
    end
  end

  cookies
end

Instance Method Details

#domain_match(request_domain) ⇒ Object

From RFC2965 Section 1.

Host A’s name domain-matches host B’s if

  • their host name strings string-compare equal; or

  • A is a HDN string and has the form NB, where N is a non-empty name string, B has the form .B’, and B’ is a HDN string. (So, x.y.com domain-matches .Y.com but not Y.com.)



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/cookie_store/cookie.rb', line 137

def domain_match(request_domain)
  request_domain = request_domain.downcase

  return true if domain == request_domain
  
  return false if request_domain =~ IPADDR
  
  return true if domain == ".#{request_domain}"
  
  return false if !domain.include?('.') && domain != 'local'
  
  return false if !request_domain.end_with?(domain)

  return !(request_domain[0...-domain.length].count('.') > (request_domain[-domain.length-1] == '.' ? 1 : 0))
end

#expired?Boolean

Indicates whether the cookie is currently considered valid

Returns:

  • (Boolean)


93
94
95
# File 'lib/cookie_store/cookie.rb', line 93

def expired?
  expires_at && Time.now > expires_at
end

#expires_atTime?

Evaluate when this cookie will expire. Uses the original cookie fields for a max-age or expires

Returns:

  • (Time, nil)

    Time of expiry, if this cookie has an expiry set



82
83
84
85
86
87
88
# File 'lib/cookie_store/cookie.rb', line 82

def expires_at
  if max_age
    created_at + max_age
  else
    expires
  end
end

#path_match(request_path) ⇒ Object

From RFC2965 Section 1.

For two strings that represent paths, P1 and P2, P1 path-matches P2 if P2 is a prefix of P1 (including the case where P1 and P2 string- compare equal). Thus, the string /tec/waldo path-matches /tec.



124
125
126
# File 'lib/cookie_store/cookie.rb', line 124

def path_match(request_path)
  request_path.start_with?(path)
end

#port_match(request_port) ⇒ Object

From RFC2965 Section 3.3

The default behavior is that a cookie MAY be returned to any request-port.

If the port attribute is set the port must be in the port-list.



158
159
160
161
# File 'lib/cookie_store/cookie.rb', line 158

def port_match(request_port)
  return true unless ports
  ports.include?(request_port)
end

#request_match?(request_uri) ⇒ Boolean

Returns a true if the request_uri is a domain-match, a path-match, and a port-match

Returns:

  • (Boolean)


114
115
116
117
# File 'lib/cookie_store/cookie.rb', line 114

def request_match?(request_uri)
  uri = request_uri.is_a?(URI) ? request_uri : URI.parse(request_uri)
  domain_match(uri.host) && path_match(uri.path) &&  port_match(uri.port)
end

#session?Boolean

Indicates whether the cookie will be considered invalid after the end of the current user session

Returns:

  • (Boolean)


100
101
102
# File 'lib/cookie_store/cookie.rb', line 100

def session?
  !expires_at || discard
end

#to_sObject



104
105
106
107
108
109
110
# File 'lib/cookie_store/cookie.rb', line 104

def to_s
  if value.include?('"')
    "#{name}=\"#{value.gsub('"', '\\"')}\""
  else
    "#{name}=#{value}"
  end
end