1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
# :markup: markdown
require 'http/cookie_jar'
# CookiestxtSaver saves and loads cookies in the cookies.txt format.
class HTTP::CookieJar::CookiestxtSaver < HTTP::CookieJar::AbstractSaver
# :singleton-method: new
# :call-seq:
# new(**options)
#
# Available option keywords are below:
#
# * `:header`
#
# Specifies the header line not including a line feed, which is
# only used by #save(). None is output if nil is
# given. (default: `"# HTTP Cookie File"`)
#
# * `:linefeed`
#
# Specifies the line separator (default: `"\n"`).
##
def save(io, jar)
io.puts @header if @header
jar.each { |cookie|
next if !@session && cookie.session?
io.print cookie_to_record(cookie)
}
end
def load(io, jar)
io.each_line { |line|
cookie = parse_record(line) and jar.add(cookie)
}
end
private
def default_options
{
:header => "# HTTP Cookie File",
:linefeed => "\n",
}
end
# :stopdoc:
True = "TRUE"
False = "FALSE"
HTTPONLY_PREFIX = '#HttpOnly_'
RE_HTTPONLY_PREFIX = /\A#{HTTPONLY_PREFIX}/
# :startdoc:
# Serializes the cookie into a cookies.txt line.
def cookie_to_record(cookie)
cookie.instance_eval {
[
@httponly ? HTTPONLY_PREFIX + dot_domain : dot_domain,
@for_domain ? True : False,
@path,
@secure ? True : False,
expires.to_i,
@name,
@value
]
}.join("\t") << @linefeed
end
# Parses a line from cookies.txt and returns a cookie object if the
# line represents a cookie record or returns nil otherwise.
def parse_record(line)
case line
when RE_HTTPONLY_PREFIX
httponly = true
line = $'
when /\A#/
return nil
else
httponly = false
end
domain,
s_for_domain, # Whether this cookie is for domain
path, # Path for which the cookie is relevant
s_secure, # Requires a secure connection
s_expires, # Time the cookie expires (Unix epoch time)
name, value = line.split("\t", 7)
return nil if value.nil?
value.chomp!
if (expires_seconds = s_expires.to_i).nonzero?
expires = Time.at(expires_seconds)
return nil if expires < Time.now
end
HTTP::Cookie.new(name, value,
:domain => domain,
:for_domain => s_for_domain == True,
:path => path,
:secure => s_secure == True,
:httponly => httponly,
:expires => expires)
end
end
|