Class: Arrow::Cookie

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

Overview

The Arrow::Cookie class, a class for parsing and generating HTTP cookies.

Large parts of this code were copied from the Webrick::Cookie class in the Ruby standard library. The copyright statements for that module are:

Author: IPR -- Internet Programming with Ruby -- writers
Copyright (c) 2000, 2001 TAKAHASHI Masayoshi, GOTOU Yuuzou
Copyright (c) 2002 Internet Programming with Ruby writers. All rights
reserved.

VCS Id

$Id$

Authors

Please see the file LICENSE in the top-level directory for licensing details.

Constant Summary collapse

CookieDateFormat =
'%a, %d-%b-%Y %H:%M:%S GMT'
CookieVersion =

RFC 2109: HTTP State Management Mechanism When it sends a request to an origin server, the user agent sends a Cookie request header to the origin server if it has cookies that are applicable to the request, based on

* the request-host;
* the request-URI;
* the cookie's age.

The syntax for the header is:

cookie = “Cookie:” cookie-version

1*((";" | ",") cookie-value)

cookie-value = NAME “=” VALUE [“;” path] [“;” domain] cookie-version = “$Version” “=” value NAME = attr VALUE = value path = “$Path” “=” value domain = “$Domain” “=” value

/\$Version\s*=\s*(.+)\s*[,;]/
CookiePath =
/\$Path/i
CookieDomain =
/\$Domain/i
CTLs =

RFC2068: Hypertext Transfer Protocol – HTTP/1.1 CTL = <any US-ASCII control character

(octets 0 - 31) and DEL (127)>

token = 1*<any CHAR except CTLs or tspecials>

tspecials = “(” | “)” | “<” | “>” | “@”

| "," | ";" | ":" | "\" | <">
| "/" | "[" | "]" | "?" | "="
| "{" | "}" | SP | HT
"[:cntrl:]"
TSpecials =
Regexp.quote ' "(),/:;<=>?@[\\]{}'
NonTokenChar =
/[#{CTLs}#{TSpecials}]/s
HTTPToken =
/\A[^#{CTLs}#{TSpecials}]+\z/s

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Object

deprecate_class_method, deprecate_method, inherited

Constructor Details

#initialize(name, values, options = {}) ⇒ Cookie

Create a new Arrow::Cookie object with the specified name and values.



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/arrow/cookie.rb', line 145

def initialize( name, values, options={} )
	values = [ values ] unless values.is_a?( Array )
	@name = name
	@values = values

	@domain = nil
	@path = nil
	@secure = false
	@comment = nil
	@max_age = nil
	@expires = nil
	@version = 0
	
	options.each do |meth, val|
		self.__send__( "#{meth}=", val )
	end
end

Instance Attribute Details

#commentObject

Because cookies can contain private information about a user, the Cookie attribute allows an origin server to document its intended use of a cookie. The user can inspect the information to decide whether to initiate or continue a session with this cookie.



197
198
199
# File 'lib/arrow/cookie.rb', line 197

def comment
  @comment
end

#domainObject

The domain the cookie belongs to



179
180
181
# File 'lib/arrow/cookie.rb', line 179

def domain
  @domain
end

#expiresObject

The cookie’s expiration (a Time object)



188
189
190
# File 'lib/arrow/cookie.rb', line 188

def expires
  @expires
end

#max_ageObject

The lifetime of the cookie, in seconds.



191
192
193
# File 'lib/arrow/cookie.rb', line 191

def max_age
  @max_age
end

#nameObject

The name of the cookie



170
171
172
# File 'lib/arrow/cookie.rb', line 170

def name
  @name
end

#pathObject

The path the cookie applies to



182
183
184
# File 'lib/arrow/cookie.rb', line 182

def path
  @path
end

#secure=(value) ⇒ Object (writeonly)

The cookie’s ‘secure’ flag.



185
186
187
# File 'lib/arrow/cookie.rb', line 185

def secure=(value)
  @secure = value
end

#valuesObject

The Array of cookie values



173
174
175
# File 'lib/arrow/cookie.rb', line 173

def values
  @values
end

#versionObject

The cookie version. 0 (the default) is fine for most uses



176
177
178
# File 'lib/arrow/cookie.rb', line 176

def version
  @version
end

Class Method Details

.dequote(string) ⇒ Object

Strip surrounding double quotes from a copy of the specified string and return it.



36
37
38
# File 'lib/arrow/cookie.rb', line 36

def self::dequote( string )
	/^"((?:[^"]+|\\.)*)"/.match( string ) ? $1 : string.dup
end

.parse(header) ⇒ Object

Parse the specified ‘Cookie:’ header value and return a Hash of one or more new Arrow::Cookie objects, keyed by name.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/arrow/cookie.rb', line 90

def self::parse( header )
	return {} if header.nil? or header.empty?
	Arrow::Logger[self].debug "Parsing cookie header: %p" % [ header ]
	cookies = []
	version = 0
	header = header.strip

	# "$Version" = value
	if CookieVersion.match( header )
		Arrow::Logger[self].debug "  Found cookie version %p" % [ $1 ]
		version = Integer( dequote($1) )
		header.slice!( CookieVersion )
	end

	# 1*((";" | ",") NAME "=" VALUE [";" path] [";" domain])
	header.split( /[,;]\s*/ ).each do |pair|
		Arrow::Logger[self].debug "  Found pair %p" % [ pair ]
		key, valstr = pair.split( /=/, 2 ).collect {|s| s.strip }
		
		case key
		when CookiePath
			Arrow::Logger[self].debug "    -> cookie-path %p" % [ valstr ]
			cookies.last.path = dequote( valstr ) unless cookies.empty?

		when CookieDomain
			Arrow::Logger[self].debug "    -> cookie-domain %p" % [ valstr ]
			cookies.last.domain = dequote( valstr ) unless cookies.empty?

		when HTTPToken
			values = parse_valuestring( valstr )
			Arrow::Logger[self].debug "    -> cookie-values %p" % [ values ]
			cookies << new( key, values, :version => version )
			
		else
			Arrow::Logger[self].warning \
				"Malformed cookie header %p: %p is not a valid token; ignoring" %
				[ header, key ]
		end
	end

	# Turn the array into a Hash, ignoring all but the first instance of
	# a cookie with the same name
	return cookies.inject({}) do |hash,cookie|
		hash[cookie.name] = cookie unless hash.key?( cookie.name )
		hash
	end
end

.parse_valuestring(valstr) ⇒ Object

Parse a cookie value string, returning an Array of Strings



42
43
44
45
46
47
# File 'lib/arrow/cookie.rb', line 42

def self::parse_valuestring( valstr )
	return [] unless valstr
	valstr = dequote( valstr )

	return valstr.split('&').collect{|str| URI.unescape(str) }
end

Instance Method Details

#eql?(other_cookie) ⇒ Boolean

Return true if other_cookie has the same name as the receiver.

Returns:

  • (Boolean)


289
290
291
# File 'lib/arrow/cookie.rb', line 289

def eql?( other_cookie )
	return (self.name == other_cookie.name) ? true : false
end

#expire!Object

Set the cookie expiration to a time in the past



265
266
267
# File 'lib/arrow/cookie.rb', line 265

def expire!
	self.expires = Time.at(0)
end

#hashObject

Generate a Fixnum hash value for this object. Uses the hash of the cookie’s name.



295
296
297
# File 'lib/arrow/cookie.rb', line 295

def hash
	return self.name.hash
end

#secure?Boolean

Returns true if the secure flag is set

Returns:

  • (Boolean)


207
208
209
# File 'lib/arrow/cookie.rb', line 207

def secure?
	return @secure ? true : false
end

#to_sObject

Return the cookie as a String



272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/arrow/cookie.rb', line 272

def to_s
	rval = "%s=%s" % [ self.name, make_valuestring(self.values) ]

	rval << make_field( "Version", self.version ) if self.version.nonzero?
	rval << make_field( "Domain", self.domain )
	rval << make_field( "Expires", make_cookiedate(self.expires) ) if self.expires
	rval << make_field( "Max-Age", self.max_age )
	rval << make_field( "Comment", self.comment )
	rval << make_field( "Path", self.path )

	rval << "; " << "Secure" if self.secure?

	return rval
end

#valueObject

Return the first value stored in the cookie as a String.



201
202
203
# File 'lib/arrow/cookie.rb', line 201

def value
	@values.first
end