lib/rufus/verbs/cookies.rb in rufus-verbs-0.10 vs lib/rufus/verbs/cookies.rb in rufus-verbs-1.0.0
- old
+ new
@@ -1,327 +1,317 @@
-#
#--
-# Copyright (c) 2008, John Mettraux, jmettraux@gmail.com
+# Copyright (c) 2008-2010, John Mettraux, jmettraux@gmail.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
-#
+#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
-#
+#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
-# (MIT license)
+# Made in Japan.
#++
-#
-#
-# John Mettraux
-#
-# Made in Japan
-#
-# 2008/01/19
-#
require 'webrick/cookie'
-#require 'rubygems'
require 'rufus/lru'
module Rufus
module Verbs
+ #
+ # Cookies related methods
+ #
+ # http://www.ietf.org/rfc/rfc2109.txt
+ #
+ module CookieMixin
+
#
- # Cookies related methods
+ # making the cookie jar available
#
- # http://www.ietf.org/rfc/rfc2109.txt
+ attr_reader :cookies
+
+ protected
+
#
- module CookieMixin
+ # Prepares the instance variable @cookies for storing
+ # cooking for this endpoint.
+ #
+ # Reads the :cookies endpoint option for determining the
+ # size of the cookie jar (77 by default).
+ #
+ def prepare_cookie_jar
- #
- # making the cookie jar available
- #
- attr_reader :cookies
+ o = @opts[:cookies]
- protected
+ return unless o and o != false
- #
- # Prepares the instance variable @cookies for storing
- # cooking for this endpoint.
- #
- # Reads the :cookies endpoint option for determining the
- # size of the cookie jar (77 by default).
- #
- def prepare_cookie_jar
+ s = o.to_s.to_i
+ s = 77 if s < 1
- o = @opts[:cookies]
+ @cookies = CookieJar.new s
+ end
- return unless o and o != false
+ #
+ # Parses the HTTP response for a potential 'Set-Cookie' header,
+ # parses and returns it as a hash.
+ #
+ def parse_cookies (response)
- s = o.to_s.to_i
- s = 77 if s < 1
+ c = response['Set-Cookie']
+ return nil unless c
+ Cookie.parse_set_cookies c
+ end
- @cookies = CookieJar.new s
- end
+ #
+ # (This method will have no effect if the EndPoint is not
+ # tracking cookies)
+ #
+ # Registers a potential cookie set by the server.
+ #
+ def register_cookies (response, opts)
- #
- # Parses the HTTP response for a potential 'Set-Cookie' header,
- # parses and returns it as a hash.
- #
- def parse_cookies (response)
+ return unless @cookies
- c = response['Set-Cookie']
- return nil unless c
- Cookie.parse_set_cookies c
- end
+ cs = parse_cookies response
- #
- # (This method will have no effect if the EndPoint is not
- # tracking cookies)
- #
- # Registers a potential cookie set by the server.
- #
- def register_cookies (response, opts)
+ return unless cs
- return unless @cookies
+ # "The origin server effectively ends a session by
+ # sending the client a Set-Cookie header with Max-Age=0"
- cs = parse_cookies response
+ cs.each do |c|
- return unless cs
+ host = opts[:host]
+ path = opts[:path]
+ cpath = c.path || "/"
- # "The origin server effectively ends a session by
- # sending the client a Set-Cookie header with Max-Age=0"
+ next unless cookie_acceptable?(opts, response, c)
- cs.each do |c|
+ domain = c.domain || host
- host = opts[:host]
- path = opts[:path]
- cpath = c.path || "/"
+ if c.max_age == 0
+ @cookies.remove_cookie domain, path, c
+ else
+ @cookies.add_cookie domain, path, c
+ end
+ end
+ end
- next unless cookie_acceptable?(opts, response, c)
+ #
+ # Checks if the cookie is acceptable in the context of
+ # the request that sent it.
+ #
+ def cookie_acceptable? (opts, response, cookie)
- domain = c.domain || host
+ # reject if :
+ #
+ # * The value for the Path attribute is not a prefix of the
+ # request-URI.
+ # * The value for the Domain attribute contains no embedded dots
+ # or does not start with a dot.
+ # * The value for the request-host does not domain-match the
+ # Domain attribute.
+ # * The request-host is a FQDN (not IP address) and has the form
+ # HD, where D is the value of the Domain attribute, and H is a
+ # string that contains one or more dots.
- if c.max_age == 0
- @cookies.remove_cookie domain, path, c
- else
- @cookies.add_cookie domain, path, c
- end
- end
- end
+ cdomain = cookie.domain
- #
- # Checks if the cookie is acceptable in the context of
- # the request that sent it.
- #
- def cookie_acceptable? (opts, response, cookie)
+ if cdomain
- # reject if :
- #
- # * The value for the Path attribute is not a prefix of the
- # request-URI.
- # * The value for the Domain attribute contains no embedded dots
- # or does not start with a dot.
- # * The value for the request-host does not domain-match the
- # Domain attribute.
- # * The request-host is a FQDN (not IP address) and has the form
- # HD, where D is the value of the Domain attribute, and H is a
- # string that contains one or more dots.
+ return false unless cdomain.index '.'
+ return false if cdomain[0, 1] != '.'
- cdomain = cookie.domain
+ h, d = split_host(opts[:host])
+ return false if d != cdomain
+ end
- if cdomain
+ #path = opts[:path]
+ path = response.request.path
- return false unless cdomain.index '.'
- return false if cdomain[0, 1] != '.'
+ cpath = cookie.path || "/"
- h, d = split_host(opts[:host])
- return false if d != cdomain
- end
+ return false if path[0..cpath.length-1] != cpath
- #path = opts[:path]
- path = response.request.path
+ true
+ end
- cpath = cookie.path || "/"
+ #
+ # Places the 'Cookie' header in the request if appropriate.
+ #
+ # (This method will have no effect if the EndPoint is not
+ # tracking cookies)
+ #
+ def mention_cookies (request, opts)
- return false if path[0..cpath.length-1] != cpath
+ return unless @cookies
- true
- end
+ cs = @cookies.fetch_cookies opts[:host], opts[:path]
- #
- # Places the 'Cookie' header in the request if appropriate.
- #
- # (This method will have no effect if the EndPoint is not
- # tracking cookies)
- #
- def mention_cookies (request, opts)
+ request['Cookie'] = cs.collect { |c| c.to_header_s }.join(",")
+ end
+ end
- return unless @cookies
+ #
+ # An extension of the cookie implementation found in WEBrick.
+ #
+ # Unmodified for now.
+ #
+ class Cookie < WEBrick::Cookie
- cs = @cookies.fetch_cookies opts[:host], opts[:path]
+ def to_header_s
- request['Cookie'] = cs.collect { |c| c.to_header_s }.join(",")
- end
+ ret = ''
+ ret << @name << '=' << @value
+ ret << '; ' << '$Version=' << @version.to_s if @version > 0
+ ret << '; ' << '$Domain=' << @domain if @domain
+ ret << '; ' << '$Port=' << @port if @port
+ ret << '; ' << '$Path=' << @path if @path
+ ret
end
+ end
- #
- # An extension of the cookie implementation found in WEBrick.
- #
- # Unmodified for now.
- #
- class Cookie < WEBrick::Cookie
+ #
+ # Cookies are stored by domain, they via this CookieKey which gathers
+ # path and name of the cookie.
+ #
+ class CookieKey
- def to_header_s
+ attr_reader :name, :path
- ret = ""
- ret << @name << "=" << @value
- ret << "; " << "$Version=" << @version.to_s if @version > 0
- ret << "; " << "$Domain=" << @domain if @domain
- ret << "; " << "$Port=" << @port if @port
- ret << "; " << "$Path=" << @path if @path
- ret
- end
+ def initialize (path, cookie)
+
+ @name = cookie.name
+ @path = path || cookie.path
end
#
- # Cookies are stored by domain, they via this CookieKey which gathers
- # path and name of the cookie.
+ # longer paths first
#
- class CookieKey
+ def <=> (other)
- attr_reader :name, :path
+ -1 * (@path <=> other.path)
+ end
- def initialize (path, cookie)
+ def hash
+ "#{@name}|#{@path}".hash
+ end
- @name = cookie.name
- @path = path || cookie.path
- end
+ def == (other)
+ (@path == other.path and @name == other.name)
+ end
- #
- # longer paths first
- #
- def <=> (other)
+ alias eql? ==
+ end
- -1 * (@path <=> other.path)
- end
+ #
+ # A few methods about hostnames.
+ #
+ # (in a mixin... could be helpful somewhere else later)
+ #
+ module HostMixin
- def hash
- "#{@name}|#{@path}".hash
- end
+ #
+ # Matching a classical IP address (not a v6 though).
+ # Should be sufficient for now.
+ #
+ IP_REGEX = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
- def == (other)
- (@path == other.path and @name == other.name)
- end
-
- alias eql? ==
- end
-
#
- # A few methods about hostnames.
+ # Returns a pair host/domain, note that the domain starts with a dot.
#
- # (in a mixin... could be helpful somewhere else later)
+ # split_host('localhost') --> [ 'localhost', nil ]
+ # split_host('benz.car.co.nz') --> [ 'benz', '.car.co.nz' ]
+ # split_host('127.0.0.1') --> [ '127.0.0.1', nil ]
+ # split_host('::1') --> [ '::1', nil ]
#
- module HostMixin
+ def split_host (host)
- #
- # Matching a classical IP address (not a v6 though).
- # Should be sufficient for now.
- #
- IP_REGEX = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
+ return [ host, nil ] if IP_REGEX.match host
+ i = host.index('.')
+ return [ host, nil ] unless i
+ [ host[0..i-1], host[i..-1] ]
+ end
+ end
- #
- # Returns a pair host/domain, note that the domain starts with a dot.
- #
- # split_host('localhost') --> [ 'localhost', nil ]
- # split_host('benz.car.co.nz') --> [ 'benz', '.car.co.nz' ]
- # split_host('127.0.0.1') --> [ '127.0.0.1', nil ]
- # split_host('::1') --> [ '::1', nil ]
- #
- def split_host (host)
+ #
+ # The container for cookies. Features methods for storing and retrieving
+ # cookies easily.
+ #
+ class CookieJar
+ include HostMixin
- return [ host, nil ] if IP_REGEX.match host
- i = host.index('.')
- return [ host, nil ] unless i
- [ host[0..i-1], host[i..-1] ]
- end
+ def initialize (jar_size)
+
+ @per_domain = LruHash.new jar_size
end
#
- # The container for cookies. Features methods for storing and retrieving
- # cookies easily.
+ # Returns the count of cookies currently stored in this jar.
#
- class CookieJar
- include HostMixin
+ def size
- def initialize (jar_size)
+ @per_domain.keys.inject(0) { |i, d| i + @per_domain[d].size }
+ end
- @per_domain = LruHash.new jar_size
- end
+ def add_cookie (domain, path, cookie)
- #
- # Returns the count of cookies currently stored in this jar.
- #
- def size
+ (@per_domain[domain] ||= {})[CookieKey.new(path, cookie)] = cookie
+ end
- @per_domain.keys.inject(0) { |i, d| i + @per_domain[d].size }
- end
+ def remove_cookie (domain, path, cookie)
- def add_cookie (domain, path, cookie)
+ (d = @per_domain[domain])
+ return unless d
+ d.delete CookieKey.new(path, cookie)
+ end
- (@per_domain[domain] ||= {})[CookieKey.new(path, cookie)] = cookie
- end
+ #
+ # Retrieves the cookies that matches the combination host/path.
+ # If the retrieved cookie is expired, will remove it from the jar
+ # and return nil.
+ #
+ def fetch_cookies (host, path)
- def remove_cookie (domain, path, cookie)
+ c = do_fetch(@per_domain[host], path)
- (d = @per_domain[domain])
- return unless d
- d.delete CookieKey.new(path, cookie)
- end
+ h, d = split_host host
+ c += do_fetch(@per_domain[d], path) if d
- #
- # Retrieves the cookies that matches the combination host/path.
- # If the retrieved cookie is expired, will remove it from the jar
- # and return nil.
- #
- def fetch_cookies (host, path)
+ c
+ end
- c = do_fetch(@per_domain[host], path)
+ private
- h, d = split_host host
- c += do_fetch(@per_domain[d], path) if d
+ #
+ # Returns all the cookies that match a domain (host) and a path.
+ #
+ def do_fetch (dh, path)
- c
- end
+ return [] unless dh
- private
-
- #
- # Returns all the cookies that match a domain (host) and a path.
- #
- def do_fetch (dh, path)
-
- return [] unless dh
-
- keys = dh.keys.sort.find_all do |k|
- path[0..k.path.length-1] == k.path
- end
- keys.inject([]) do |r, k|
- r << dh[k]
- r
- end
- end
+ keys = dh.keys.sort.find_all do |k|
+ path[0..k.path.length-1] == k.path
+ end
+ keys.inject([]) do |r, k|
+ r << dh[k]
+ r
+ end
end
+ end
end
end