mirror of
https://github.com/samsonjs/http-cookie.git
synced 2026-03-25 08:55:53 +00:00
185 lines
3.7 KiB
Ruby
185 lines
3.7 KiB
Ruby
module HTTP
|
|
autoload :Cookie, 'http/cookie'
|
|
end
|
|
|
|
##
|
|
# This class is used to manage the Cookies that have been returned from
|
|
# any particular website.
|
|
|
|
class HTTP::CookieJar
|
|
include Enumerable
|
|
|
|
attr_reader :jar
|
|
|
|
def initialize
|
|
@jar = {}
|
|
end
|
|
|
|
def initialize_copy other # :nodoc:
|
|
@jar = Marshal.load Marshal.dump other.jar
|
|
end
|
|
|
|
# Add a +cookie+ to the jar and return self.
|
|
def add(cookie)
|
|
if cookie.domain.nil? || cookie.path.nil?
|
|
raise ArgumentError, "a cookie with unknown domain or path cannot be added"
|
|
end
|
|
normal_domain = cookie.domain_name.hostname
|
|
|
|
((@jar[normal_domain] ||= {})[cookie.path] ||= {})[cookie.name] = cookie
|
|
|
|
self
|
|
end
|
|
alias << add
|
|
|
|
# Fetch the cookies that should be used for the URL/URI.
|
|
def cookies(url)
|
|
now = Time.now
|
|
each(url).select { |cookie|
|
|
!cookie.expired? && (cookie.accessed_at = now)
|
|
}.sort
|
|
end
|
|
|
|
def empty?(url)
|
|
cookies(url).empty?
|
|
end
|
|
|
|
# Iterate over cookies. If +uri+ is given, cookies not for the
|
|
# URL/URI are excluded.
|
|
def each(uri = nil, &block)
|
|
block_given? or return enum_for(__method__, uri)
|
|
|
|
if uri
|
|
block = proc { |cookie|
|
|
yield cookie if cookie.valid_for_uri?(uri)
|
|
}
|
|
end
|
|
|
|
@jar.each { |domain, paths|
|
|
paths.each { |path, hash|
|
|
hash.each_value(&block)
|
|
}
|
|
}
|
|
self
|
|
end
|
|
|
|
# call-seq:
|
|
# jar.save_as(file, format = :yaml)
|
|
# jar.save_as(file, options)
|
|
#
|
|
# Save the cookie jar to a file in the format specified and return
|
|
# self.
|
|
#
|
|
# Available option keywords are below:
|
|
#
|
|
# * +format+
|
|
# [<tt>:yaml</tt>]
|
|
# YAML structure (default)
|
|
# [<tt>:cookiestxt</tt>]
|
|
# Mozilla's cookies.txt format
|
|
# * +session+
|
|
# [+true+]
|
|
# Save session cookies as well.
|
|
# [+false+]
|
|
# Do not save session cookies. (default)
|
|
def save_as(file, options = nil)
|
|
if Symbol === options
|
|
format = options
|
|
session = false
|
|
else
|
|
options ||= {}
|
|
format = options[:format] || :yaml
|
|
session = !!options[:session]
|
|
end
|
|
|
|
jar = dup
|
|
jar.cleanup !session
|
|
|
|
open(file, 'w') { |f|
|
|
case format
|
|
when :yaml then
|
|
load_yaml
|
|
|
|
YAML.dump(jar.jar, f)
|
|
when :cookiestxt then
|
|
jar.dump_cookiestxt(f)
|
|
else
|
|
raise ArgumentError, "Unknown cookie jar file format"
|
|
end
|
|
}
|
|
|
|
self
|
|
end
|
|
|
|
# Load cookie jar from a file in the format specified.
|
|
#
|
|
# Available formats:
|
|
# :yaml <- YAML structure.
|
|
# :cookiestxt <- Mozilla's cookies.txt format
|
|
def load(file, format = :yaml)
|
|
open(file) { |f|
|
|
case format
|
|
when :yaml then
|
|
load_yaml
|
|
@jar = YAML.load(f)
|
|
when :cookiestxt then
|
|
load_cookiestxt(f)
|
|
else
|
|
raise ArgumentError, "Unknown cookie jar file format"
|
|
end
|
|
}
|
|
|
|
cleanup
|
|
end
|
|
|
|
def load_yaml # :nodoc:
|
|
begin
|
|
require 'psych'
|
|
rescue LoadError
|
|
end
|
|
|
|
require 'yaml'
|
|
end
|
|
|
|
# Clear the cookie jar and return self.
|
|
def clear
|
|
@jar = {}
|
|
self
|
|
end
|
|
|
|
# Read cookies from Mozilla cookies.txt-style IO stream and return
|
|
# self.
|
|
def load_cookiestxt(io)
|
|
now = Time.now
|
|
|
|
io.each_line do |line|
|
|
c = HTTP::Cookie.parse_cookiestxt_line(line) and add(c)
|
|
end
|
|
|
|
self
|
|
end
|
|
|
|
# Write cookies to Mozilla cookies.txt-style IO stream and return
|
|
# self.
|
|
def dump_cookiestxt(io)
|
|
to_a.each do |cookie|
|
|
io.print cookie.to_cookiestxt_line
|
|
end
|
|
self
|
|
end
|
|
|
|
protected
|
|
|
|
# Remove expired cookies and return self.
|
|
def cleanup session = false
|
|
@jar.each do |domain, paths|
|
|
paths.each do |path, hash|
|
|
hash.delete_if { |cookie_name, cookie|
|
|
cookie.expired? or (session and cookie.session)
|
|
}
|
|
end
|
|
end
|
|
self
|
|
end
|
|
end
|
|
|