Skip to content
Snippets Groups Projects
Commit e4890f38 authored by Ajayi Olatunji O.'s avatar Ajayi Olatunji O.
Browse files

New upstream version 1.0.5

parent 2daa161d
Branches upstream
Tags upstream/1.0.5
No related merge requests found
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- "*"
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu]
# We still kind of support Ruby 1.8.7
ruby: [2.7, "3.0", 3.1, head, jruby]
name: >-
${{matrix.os}}:ruby-${{matrix.ruby}}
runs-on: ${{matrix.os}}-latest
continue-on-error: ${{matrix.ruby == 'head' || matrix.ruby == 'jruby'}}
steps:
- name: Check out
uses: actions/checkout@v2
- name: Set up ruby and bundle
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{matrix.ruby}}
bundler-cache: true
- name: Run rake
run: |
bundle exec rake
sudo: false
language: ruby
cache: bundler
rvm:
- 1.8.7
- ree
- 1.9.3
- 2.0.0
- 2.1
- 2.2
- 2.3.0
- ruby-head
- jruby-1.7
- jruby-9
- rbx-2
matrix:
allow_failures:
- rvm: ruby-head
- rvm: rbx-2
before_install:
- gem update bundler
## 1.0.5 (2022-05-25)
- Silence SQLite3 warnings
## 1.0.4 (2021-06-07)
- Support Mozilla's cookie storage format up to version 7.
- Fix the time representation with creationTime and lastAccessed in
MozillaStore. (#8)
## 1.0.3 (2016-09-30)
- Treat comma as normal character in HTTP::Cookie.cookie_value_to_hash
......
......@@ -25,10 +25,11 @@ Gem::Specification.new do |gem|
gem.extra_rdoc_files = ['README.md', 'LICENSE.txt']
gem.add_runtime_dependency("domain_name", ["~> 0.5"])
gem.add_development_dependency("sqlite3", ["~> 1.3.3"]) unless defined?(JRUBY_VERSION)
gem.add_development_dependency("sqlite3", ["~> 1.3"]) unless defined?(JRUBY_VERSION)
gem.add_development_dependency("bundler", [">= 1.2.0"])
gem.add_development_dependency("test-unit", [">= 2.4.3", *("< 3" if RUBY_VERSION < "1.9")])
gem.add_development_dependency("rake", [">= 0.9.2.2", *("< 11" if RUBY_VERSION < "1.9")])
gem.add_development_dependency("rdoc", ["> 2.4.2"])
gem.add_development_dependency("rdoc", RUBY_VERSION > "1.9" ? "> 2.4.2" : "~> 2.4.2")
gem.add_development_dependency("simplecov", [">= 0"])
gem.add_development_dependency("json", ["< 2"]) if RUBY_VERSION < "2.0"
end
......@@ -128,7 +128,7 @@ class HTTP::Cookie
# new("name" => "uid", "value" => "a12345", "Domain" => 'www.example.org')
#
def initialize(*args)
@origin = @domain = @path =
@name = @origin = @domain = @path =
@expires = @max_age = nil
@for_domain = @secure = @httponly = false
@session = true
......
module HTTP
class Cookie
VERSION = "1.0.3"
VERSION = "1.0.5"
end
end
......@@ -17,8 +17,8 @@ class HTTP::CookieJar::AbstractStore
begin
require 'http/cookie_jar/%s_store' % symbol
@@class_map.fetch(symbol)
rescue LoadError, IndexError
raise IndexError, 'cookie store unavailable: %s' % symbol.inspect
rescue LoadError, IndexError => e
raise IndexError, 'cookie store unavailable: %s, error: %s' % symbol.inspect, e.message
end
end
......
......@@ -67,10 +67,8 @@ class HTTP::CookieJar
def each(uri = nil) # :yield: cookie
now = Time.now
if uri
thost = DomainName.new(uri.host)
tpath = uri.path
@jar.each { |domain, paths|
next unless thost.cookie_domain?(domain)
paths.each { |path, hash|
next unless HTTP::Cookie.path_match?(path, tpath)
hash.delete_if { |name, cookie|
......
......@@ -10,7 +10,7 @@ class HTTP::CookieJar
# stored persistently in the SQLite3 database.
class MozillaStore < AbstractStore
# :stopdoc:
SCHEMA_VERSION = 5
SCHEMA_VERSION = 7
def default_options
{
......@@ -22,14 +22,11 @@ class HTTP::CookieJar
ALL_COLUMNS = %w[
baseDomain
appId inBrowserElement
originAttributes
name value
host path
expiry creationTime lastAccessed
isSecure isHttpOnly
]
UK_COLUMNS = %w[
name host path
appId inBrowserElement
]
......@@ -95,6 +92,11 @@ class HTTP::CookieJar
def initialize(options = nil)
super
@origin_attributes = encode_www_form({}.tap { |params|
params['appId'] = @app_id if @app_id.nonzero?
params['inBrowserElement'] = 1 if @in_browser_element
})
@filename = options[:filename] or raise ArgumentError, ':filename option is missing'
@sjar = HTTP::CookieJar::HashStore.new
......@@ -134,7 +136,7 @@ class HTTP::CookieJar
# Returns the schema version of the database.
def schema_version
@schema_version ||= @db.execute("PRAGMA user_version").first[0]
@schema_version ||= @db.execute("PRAGMA user_version").first["user_version"]
rescue SQLite3::SQLException
@logger.warn "couldn't get schema version!" if @logger
return nil
......@@ -147,8 +149,8 @@ class HTTP::CookieJar
@schema_version = version
end
def create_table
self.schema_version = SCHEMA_VERSION
def create_table_v5
self.schema_version = 5
@db.execute("DROP TABLE IF EXISTS moz_cookies")
@db.execute(<<-'SQL')
CREATE TABLE moz_cookies (
......@@ -176,6 +178,62 @@ class HTTP::CookieJar
SQL
end
def create_table_v6
self.schema_version = 6
@db.execute("DROP TABLE IF EXISTS moz_cookies")
@db.execute(<<-'SQL')
CREATE TABLE moz_cookies (
id INTEGER PRIMARY KEY,
baseDomain TEXT,
originAttributes TEXT NOT NULL DEFAULT '',
name TEXT,
value TEXT,
host TEXT,
path TEXT,
expiry INTEGER,
lastAccessed INTEGER,
creationTime INTEGER,
isSecure INTEGER,
isHttpOnly INTEGER,
CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)
)
SQL
@db.execute(<<-'SQL')
CREATE INDEX moz_basedomain
ON moz_cookies (baseDomain,
originAttributes);
SQL
end
def create_table
self.schema_version = SCHEMA_VERSION
@db.execute("DROP TABLE IF EXISTS moz_cookies")
@db.execute(<<-'SQL')
CREATE TABLE moz_cookies (
id INTEGER PRIMARY KEY,
baseDomain TEXT,
originAttributes TEXT NOT NULL DEFAULT '',
name TEXT,
value TEXT,
host TEXT,
path TEXT,
expiry INTEGER,
lastAccessed INTEGER,
creationTime INTEGER,
isSecure INTEGER,
isHttpOnly INTEGER,
appId INTEGER DEFAULT 0,
inBrowserElement INTEGER DEFAULT 0,
CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)
)
SQL
@db.execute(<<-'SQL')
CREATE INDEX moz_basedomain
ON moz_cookies (baseDomain,
originAttributes);
SQL
end
def db_prepare(sql)
st = @db.prepare(sql)
yield st
......@@ -226,7 +284,7 @@ class HTTP::CookieJar
when 4
@db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
@db.execute("DROP INDEX moz_basedomain")
create_table
create_table_v5
@db.execute(<<-'SQL')
INSERT INTO moz_cookies
(baseDomain, appId, inBrowserElement, name, value, host, path, expiry,
......@@ -236,7 +294,42 @@ class HTTP::CookieJar
FROM moz_cookies_old
SQL
@db.execute("DROP TABLE moz_cookies_old")
when 5
@db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
@db.execute("DROP INDEX moz_basedomain")
create_table_v6
@db.create_function('CONVERT_TO_ORIGIN_ATTRIBUTES', 2) { |func, appId, inBrowserElement|
params = {}
params['appId'] = appId if appId.nonzero?
params['inBrowserElement'] = inBrowserElement if inBrowserElement.nonzero?
func.result = encode_www_form(params)
}
@db.execute(<<-'SQL')
INSERT INTO moz_cookies
(baseDomain, originAttributes, name, value, host, path, expiry,
lastAccessed, creationTime, isSecure, isHttpOnly)
SELECT baseDomain,
CONVERT_TO_ORIGIN_ATTRIBUTES(appId, inBrowserElement),
name, value, host, path, expiry, lastAccessed, creationTime,
isSecure, isHttpOnly
FROM moz_cookies_old
SQL
@db.execute("DROP TABLE moz_cookies_old")
when 6
@db.execute("ALTER TABLE moz_cookies ADD appId INTEGER DEFAULT 0")
@db.execute("ALTER TABLE moz_cookies ADD inBrowserElement INTEGER DEFAULT 0")
@db.create_function('SET_APP_ID', 1) { |func, originAttributes|
func.result = get_query_param(originAttributes, 'appId').to_i # nil.to_i == 0
}
@db.create_function('SET_IN_BROWSER', 1) { |func, originAttributes|
func.result = get_query_param(originAttributes, 'inBrowserElement').to_i # nil.to_i == 0
}
@db.execute(<<-'SQL')
UPDATE moz_cookies SET appId = SET_APP_ID(originAttributes),
inBrowserElement = SET_IN_BROWSER(originAttributes)
SQL
@logger.info("Upgraded database to schema version %d" % schema_version) if @logger
self.schema_version += 1
else
break
end
......@@ -259,16 +352,17 @@ class HTTP::CookieJar
def db_add(cookie)
@stmt[:add].execute({
:baseDomain => cookie.domain_name.domain || cookie.domain,
:appId => @app_id,
:inBrowserElement => @in_browser_element ? 1 : 0,
:originAttributes => @origin_attributes,
:name => cookie.name, :value => cookie.value,
:host => cookie.dot_domain,
:path => cookie.path,
:expiry => cookie.expires_at.to_i,
:creationTime => cookie.created_at.to_i,
:lastAccessed => cookie.accessed_at.to_i,
:creationTime => serialize_usectime(cookie.created_at),
:lastAccessed => serialize_usectime(cookie.accessed_at),
:isSecure => cookie.secure? ? 1 : 0,
:isHttpOnly => cookie.httponly? ? 1 : 0,
:appId => @app_id,
:inBrowserElement => @in_browser_element ? 1 : 0,
})
cleanup if (@gc_index += 1) >= @gc_threshold
......@@ -295,6 +389,36 @@ class HTTP::CookieJar
self
end
if RUBY_VERSION >= '1.9'
def encode_www_form(enum)
URI.encode_www_form(enum)
end
def get_query_param(str, key)
URI.decode_www_form(str).find { |k, v|
break v if k == key
}
end
else
require 'cgi'
def encode_www_form(enum)
enum.map { |k, v| "#{CGI.escape(k)}=#{CGI.escape(v)}" }.join('&')
end
def get_query_param(str, key)
CGI.parse(str)[key].first
end
end
def serialize_usectime(time)
time ? (time.to_f * 1e6).floor : 0
end
def deserialize_usectime(value)
Time.at(value ? value / 1e6 : 0)
end
public
def add(cookie)
......@@ -337,7 +461,6 @@ class HTTP::CookieJar
now = Time.now
if uri
thost = DomainName.new(uri.host)
tpath = uri.path
@stmt[:cookies_for_domain].execute({
:baseDomain => thost.domain || thost.hostname,
......@@ -355,8 +478,8 @@ class HTTP::CookieJar
attrs[:domain] = row['host']
attrs[:path] = row['path']
attrs[:expires_at] = Time.at(row['expiry'])
attrs[:accessed_at] = Time.at(row['lastAccessed'] || 0)
attrs[:created_at] = Time.at(row['creationTime'] || 0)
attrs[:accessed_at] = deserialize_usectime(row['lastAccessed'])
attrs[:created_at] = deserialize_usectime(row['creationTime'])
attrs[:secure] = secure
attrs[:httponly] = row['isHttpOnly'] != 0
})
......@@ -364,7 +487,7 @@ class HTTP::CookieJar
if cookie.valid_for_uri?(uri)
cookie.accessed_at = now
@stmt[:update_lastaccessed].execute({
'lastAccessed' => now.to_i,
'lastAccessed' => serialize_usectime(now),
'id' => row['id'],
})
yield cookie
......@@ -383,8 +506,8 @@ class HTTP::CookieJar
attrs[:domain] = row['host']
attrs[:path] = row['path']
attrs[:expires_at] = Time.at(row['expiry'])
attrs[:accessed_at] = Time.at(row['lastAccessed'] || 0)
attrs[:created_at] = Time.at(row['creationTime'] || 0)
attrs[:accessed_at] = deserialize_usectime(row['lastAccessed'])
attrs[:created_at] = deserialize_usectime(row['creationTime'])
attrs[:secure] = row['isSecure'] != 0
attrs[:httponly] = row['isHttpOnly'] != 0
})
......
......@@ -21,7 +21,7 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
def load(io, jar)
begin
data = YAML.load(io)
data = load_yaml(io)
rescue ArgumentError => e
case e.message
when %r{\Aundefined class/module Mechanize::}
......@@ -31,7 +31,7 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
yaml = io.read
# a gross hack
yaml.gsub!(%r{^( [^ ].*:) !ruby/object:Mechanize::Cookie$}, "\\1")
data = YAML.load(yaml)
data = load_yaml(yaml)
rescue Errno::ESPIPE
@logger.warn "could not rewind the stream for conversion" if @logger
rescue ArgumentError
......@@ -73,4 +73,14 @@ class HTTP::CookieJar::YAMLSaver < HTTP::CookieJar::AbstractSaver
def default_options
{}
end
if YAML.name == 'Psych' && Psych::VERSION >= '3.1'
def load_yaml(yaml)
YAML.safe_load(yaml, :permitted_classes => %w[Time HTTP::Cookie Mechanize::Cookie DomainName], :aliases => true)
end
else
def load_yaml(yaml)
YAML.load(yaml)
end
end
end
# -*- coding: utf-8 -*-
require File.expand_path('helper', File.dirname(__FILE__))
require 'psych' if !defined?(YAML) && RUBY_VERSION == "1.9.2"
require 'yaml'
class TestHTTPCookie < Test::Unit::TestCase
def setup
......@@ -1073,6 +1075,16 @@ class TestHTTPCookie < Test::Unit::TestCase
}
end
if YAML.name == 'Psych' && Psych::VERSION >= '3.1'
private def load_yaml(yaml)
YAML.safe_load(yaml, :permitted_classes => %w[Time HTTP::Cookie Mechanize::Cookie DomainName], :aliases => true)
end
else
private def load_yaml(yaml)
YAML.load(yaml)
end
end
def test_yaml_expires
require 'yaml'
cookie = HTTP::Cookie.new(cookie_values)
......@@ -1080,29 +1092,29 @@ class TestHTTPCookie < Test::Unit::TestCase
assert_equal false, cookie.session?
assert_equal nil, cookie.max_age
ycookie = YAML.load(cookie.to_yaml)
ycookie = load_yaml(cookie.to_yaml)
assert_equal false, ycookie.session?
assert_equal nil, ycookie.max_age
assert_in_delta cookie.expires, ycookie.expires, 1
cookie.expires = nil
ycookie = YAML.load(cookie.to_yaml)
ycookie = load_yaml(cookie.to_yaml)
assert_equal true, ycookie.session?
assert_equal nil, ycookie.max_age
cookie.expires = Time.now + 3600
ycookie = YAML.load(cookie.to_yaml)
ycookie = load_yaml(cookie.to_yaml)
assert_equal false, ycookie.session?
assert_equal nil, ycookie.max_age
assert_in_delta cookie.expires, ycookie.expires, 1
cookie.max_age = 3600
ycookie = YAML.load(cookie.to_yaml)
ycookie = load_yaml(cookie.to_yaml)
assert_equal false, ycookie.session?
assert_in_delta cookie.created_at + 3600, ycookie.expires, 1
cookie.max_age = nil
ycookie = YAML.load(cookie.to_yaml)
ycookie = load_yaml(cookie.to_yaml)
assert_equal true, ycookie.session?
assert_equal nil, ycookie.expires
end
......
......@@ -20,11 +20,7 @@ module TestHTTPCookieJar
assert_raises(NameError) {
HTTP::CookieJar::ErroneousStore
}
if RUBY_VERSION >= "1.9"
assert_includes $LOADED_FEATURES, rb
else
assert_includes $LOADED_FEATURES, rb[(dir.size + 1)..-1]
end
assert($LOADED_FEATURES.any? { |file| FileTest.identical?(file, rb) })
}
end
......@@ -45,11 +41,7 @@ module TestHTTPCookieJar
assert_raises(NameError) {
HTTP::CookieJar::ErroneousSaver
}
if RUBY_VERSION >= "1.9"
assert_includes $LOADED_FEATURES, rb
else
assert_includes $LOADED_FEATURES, rb[(dir.size + 1)..-1]
end
assert($LOADED_FEATURES.any? { |file| FileTest.identical?(file, rb) })
}
end
end
......@@ -139,6 +131,17 @@ module TestHTTPCookieJar
assert_equal(0, @jar.cookies(URI('http://www.rubyforge.org/')).length)
end
def test_host_only_with_unqualified_hostname
@jar.add(HTTP::Cookie.new(cookie_values(
:origin => 'http://localhost/', :domain => 'localhost', :for_domain => false)))
assert_equal(1, @jar.cookies(URI('http://localhost/')).length)
assert_equal(1, @jar.cookies(URI('http://Localhost/')).length)
assert_equal(1, @jar.cookies(URI('https://Localhost/')).length)
end
def test_empty_value
url = URI 'http://rubyforge.org/'
values = cookie_values(:value => "")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment