class WebAgent::CookieManager
def add(given)
def add(given) check_domain(given.domain, given.url.host, given.override?) domain = given.domain || given.url.host path = given.path || given.url.path.sub(%r|/[^/]*\z|, '') cookie = nil @cookies.synchronize do check_expired_cookies cookie = @cookies.find { |c| c.domain == domain && c.path == path && c.name == given.name } if !cookie cookie = WebAgent::Cookie.new cookie.use = true @cookies << cookie end end cookie.domain = domain cookie.path = path cookie.url = given.url cookie.name = given.name cookie.value = given.value cookie.expires = given.expires cookie.secure = given.secure? cookie.http_only = given.http_only? cookie.domain_orig = given.domain cookie.path_orig = given.path if cookie.discard? || cookie.expires.nil? cookie.discard = true else cookie.discard = false @is_saved = false end end
def check_cookie_accept_domain(domain)
def check_cookie_accept_domain(domain) unless domain return false end @accept_domains.each{|dom| if domain_match(domain, dom) return true end } @reject_domains.each{|dom| if domain_match(domain, dom) return false end } return true end
def check_domain(domain, hostname, override)
def check_domain(domain, hostname, override) return unless domain # [DRAFT 12] s. 4.2.2 (does not apply in the case that # host name is the same as domain attribute for version 0 # cookie) # I think that this rule has almost the same effect as the # tail match of [NETSCAPE]. if domain !~ /^\./ && hostname != domain domain = '.'+domain end # [NETSCAPE] rule if @netscape_rule n = domain.scan(/\./).length if n < 2 cookie_error(SpecialError.new, override) elsif n == 2 ## [NETSCAPE] rule ok = SPECIAL_DOMAIN.select{|sdomain| sdomain == domain[-(sdomain.length)..-1] } if ok.empty? cookie_error(SpecialError.new, override) end end end # this implementation does not check RFC2109 4.3.2 case 2; # the portion of host not in domain does not contain a dot. # according to nsCookieService.cpp in Firefox 3.0.4, Firefox 3.0.4 # and IE does not check, too. end
def check_expired_cookies
def check_expired_cookies @cookies.reject!{|cookie| is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime)) if is_expired && !cookie.discard? @is_saved = false end is_expired } end
def cookie_error(err, override)
def cookie_error(err, override) if !err.kind_of?(ErrorOverrideOK) || !override raise err end end
def cookies=(cookies)
def cookies=(cookies) if cookies.is_a?(SynchronizedArray) @cookies = cookies else @cookies = SynchronizedArray.new(cookies) end end
def find(url)
def find(url) return nil if @cookies.empty? cookie_list = Array.new @cookies.each{|cookie| is_expired = (cookie.expires && (cookie.expires < Time.now.gmtime)) if cookie.use? && !is_expired && cookie.match?(url) if cookie_list.select{|c1| c1.name == cookie.name}.empty? cookie_list << cookie end end } return make_cookie_str(cookie_list) end
def initialize(file=nil)
def initialize(file=nil) @cookies = SynchronizedArray.new @cookies_file = file @is_saved = true @reject_domains = Array.new @accept_domains = Array.new @netscape_rule = false end
def load_cookies
def load_cookies return if !File.readable?(@cookies_file) @cookies.synchronize do @cookies.clear File.open(@cookies_file,'r'){|f| while line = f.gets cookie = WebAgent::Cookie.new @cookies << cookie col = line.chomp.split(/\t/) cookie.url = HTTPClient::Util.urify(col[0]) cookie.name = col[1] cookie.value = col[2] if col[3].empty? or col[3] == '0' cookie.expires = nil else cookie.expires = Time.at(col[3].to_i).gmtime end cookie.domain = col[4] cookie.path = col[5] cookie.set_flag(col[6]) end } end end
def make_cookie_str(cookie_list)
def make_cookie_str(cookie_list) if cookie_list.empty? return nil end ret = '' c = cookie_list.shift ret += "#{c.name}=#{c.value}" cookie_list.each{|cookie| ret += "; #{cookie.name}=#{cookie.value}" } return ret end
def parse(str, url)
def parse(str, url) cookie = WebAgent::Cookie.new cookie.parse(str, url) add(cookie) end
def save_all_cookies(force = nil, save_unused = true, save_discarded = true)
def save_all_cookies(force = nil, save_unused = true, save_discarded = true) @cookies.synchronize do check_expired_cookies if @is_saved and !force return end File.open(@cookies_file, 'w') do |f| @cookies.each do |cookie| if (cookie.use? or save_unused) and (!cookie.discard? or save_discarded) f.print(cookie.url.to_s,"\t", cookie.name,"\t", cookie.value,"\t", cookie.expires.to_i,"\t", cookie.domain,"\t", cookie.path,"\t", cookie.flag,"\n") end end end end @is_saved = true end
def save_cookies(force = nil)
def save_cookies(force = nil) save_all_cookies(force, false, false) end