Class: HTTP::CookieJar::MozillaStore

### Home Classes Methods

### In Files

- lib/http/cookie_jar/mozilla_store.rb

### Parent

HTTP::CookieJar::AbstractStore

### Namespace

- CLASS HTTP::CookieJar::MozillaStore::Database

### Methods

- ::new
- #add
- #cleanup
- #clear
- #close
- #closed?
- #create_table
- #db_add
- #db_delete
- #db_prepare
- #delete
- #each
- #initialize_copy
- #schema_version
- #schema_version=
- #upgrade_database

### Files

- LICENSE.txt

### Class/Module Index

Quicksearch

- HTTP
- HTTP::Cookie
- HTTP::Cookie::Scanner
- HTTP::CookieJar
- HTTP::CookieJar::AbstractSaver
- HTTP::CookieJar::AbstractStore
- HTTP::CookieJar::CookiestxtSaver
- HTTP::CookieJar::HashStore
- HTTP::CookieJar::MozillaStore
- HTTP::CookieJar::YAMLSaver
- Array
- Hash
- String

No matching classes.

# HTTP::CookieJar::MozillaStore

A store class that uses Mozilla compatible SQLite3 database as backing store.

Session cookies are stored separately on memory and will not be stored persistently in the SQLite3 database.

### Attributes

filename[R]

The file name of the SQLite3 database given in initialization.

### Public Class Methods

new(**options) click to toggle source

Generates a Mozilla cookie store. If the file does not exist, it is created. If it does and its schema is old, it is automatically upgraded with a new schema keeping the existing data.

Available option keywords are as below:

:filename : A file name of the SQLite3 database to open. This option is mandatory.

:gc_threshold : GC threshold; A GC happens when this many times cookies have been stored (default: `HTTP::Cookie::MAX_COOKIES_TOTAL / 20`)

:app_id : application ID (default: `0`) to have per application jar.

:in_browser_element : a flag to tell if cookies are stored in an in browser element. (default: `false`)

    # File lib/http/cookie_jar/mozilla_store.rb, line 95
    def initialize(options = nil)
      super

      @filename = options[:filename] or raise ArgumentError, ':filename option is missing'

      @sjar = HTTP::CookieJar::HashStore.new

      @db = Database.new(@filename)

      @stmt = Hash.new { |st, key|
        st[key] = @db.prepare(SQL[key])
      }

      ObjectSpace.define_finalizer(self, Callable[@db, :close])

      upgrade_database

      @gc_index = 0
    end

### Public Instance Methods

add(cookie) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 300
    def add(cookie)
      if cookie.session?
        @sjar.add(cookie)
        db_delete(cookie)
      else
        @sjar.delete(cookie)
        db_add(cookie)
      end
    end

cleanup(session = false) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 430
    def cleanup(session = false)
      synchronize {
        break if @gc_index == 0

        @stmt[:delete_expired].execute({ 'expiry' => Time.now.to_i })

        @stmt[:overusing_domains].execute({
            'count' => HTTP::Cookie::MAX_COOKIES_PER_DOMAIN
          }).each { |row|
          domain, count = row['domain'], row['count']

          @stmt[:delete_per_domain_overuse].execute({
              'domain' => domain,
              'limit' => count - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN,
            })
        }

        overrun = count - HTTP::Cookie::MAX_COOKIES_TOTAL

        if overrun > 0
          @stmt[:delete_total_overuse].execute({ 'limit' => overrun })
        end

        @gc_index = 0
      }
      self
    end

clear() click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 399
    def clear
      @db.execute("DELETE FROM moz_cookies")
      @sjar.clear
      self
    end

close() click to toggle source

Closes the SQLite3 database. After closing, any operation may raise an error.

    # File lib/http/cookie_jar/mozilla_store.rb, line 125
    def close
      @db.closed? || @db.close
      self
    end

closed?() click to toggle source

Tests if the SQLite3 database is closed.

    # File lib/http/cookie_jar/mozilla_store.rb, line 131
    def closed?
      @db.closed?
    end

delete(cookie) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 310
    def delete(cookie)
      @sjar.delete(cookie)
      db_delete(cookie)
    end

each(uri = nil) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 336
    def each(uri = nil, &block) # :yield: cookie
      now = Time.now
      if uri
        thost = DomainName.new(uri.host)
        tpath = uri.path

        @stmt[:cookies_for_domain].execute({
            :baseDomain => thost.domain || thost.hostname,
            :appId => @app_id,
            :inBrowserElement => @in_browser_element ? 1 : 0,
            :expiry => now.to_i,
          }).each { |row|
          if secure = row['isSecure'] != 0
            next unless URI::HTTPS === uri
          end

          cookie = HTTP::Cookie.new({}.tap { |attrs|
              attrs[:name]        = row['name']
              attrs[:value]       = row['value']
              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[:secure]      = secure
              attrs[:httponly]    = row['isHttpOnly'] != 0
            })

          if cookie.valid_for_uri?(uri)
            cookie.accessed_at = now
            @stmt[:update_lastaccessed].execute({
                'lastAccessed' => now.to_i,
                'id' => row['id'],
              })
            yield cookie
          end
        }
        @sjar.each(uri, &block)
      else
        @stmt[:all_cookies].execute({
            :appId => @app_id,
            :inBrowserElement => @in_browser_element ? 1 : 0,
            :expiry => now.to_i,
          }).each { |row|
          cookie = HTTP::Cookie.new({}.tap { |attrs|
              attrs[:name]        = row['name']
              attrs[:value]       = row['value']
              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[:secure]      = row['isSecure'] != 0
              attrs[:httponly]    = row['isHttpOnly'] != 0
            })

          yield cookie
        }
        @sjar.each(&block)
      end
      self
    end

initialize_copy(other) click to toggle source

Raises TypeError. Cloning is inhibited in this store class.

    # File lib/http/cookie_jar/mozilla_store.rb, line 116
    def initialize_copy(other)
      raise TypeError, 'can\t clone %s' % self.class
    end

schema_version() click to toggle source

Returns the schema version of the database.

    # File lib/http/cookie_jar/mozilla_store.rb, line 136
    def schema_version
      @schema_version ||= @db.execute("PRAGMA user_version").first[0]
    rescue SQLite3::SQLException
      @logger.warn "couldn't get schema version!" if @logger
      return nil
    end

### Protected Instance Methods

create_table() click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 150
    def create_table
      self.schema_version = SCHEMA_VERSION
      @db.execute("DROP TABLE IF EXISTS moz_cookies")
      @db.execute(                   CREATE TABLE moz_cookies (                     id INTEGER PRIMARY KEY,                     baseDomain TEXT,                     appId INTEGER DEFAULT 0,                     inBrowserElement INTEGER DEFAULT 0,                     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, appId, inBrowserElement)                   ))
      @db.execute(                   CREATE INDEX moz_basedomain                     ON moz_cookies (baseDomain,                                     appId,                                     inBrowserElement);)
    end

db_add(cookie) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 259
    def db_add(cookie)
      @stmt[:add].execute({
          :baseDomain => cookie.domain_name.domain || cookie.domain,
          :appId => @app_id,
          :inBrowserElement => @in_browser_element ? 1 : 0,
          :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,
          :isSecure => cookie.secure? ? 1 : 0,
          :isHttpOnly => cookie.httponly? ? 1 : 0,
        })
      cleanup if (@gc_index += 1) >= @gc_threshold

      self
    end

db_delete(cookie) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 287
    def db_delete(cookie)
      @stmt[:delete].execute({
          :appId => @app_id,
          :inBrowserElement => @in_browser_element ? 1 : 0,
          :name => cookie.name,
          :host => cookie.dot_domain,
          :path => cookie.path,
        })
      self
    end

db_prepare(sql) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 179
    def db_prepare(sql)
      st = @db.prepare(sql)
      yield st
    ensure
      st.close if st
    end

schema_version=(version) click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 145
    def schema_version= version
      @db.execute("PRAGMA user_version = %d" % version)
      @schema_version = version
    end

upgrade_database() click to toggle source

    # File lib/http/cookie_jar/mozilla_store.rb, line 186
    def upgrade_database
      loop {
        case schema_version
        when nil, 0
          self.schema_version = SCHEMA_VERSION
          break
        when 1
          @db.execute("ALTER TABLE moz_cookies ADD lastAccessed INTEGER")
          self.schema_version += 1
        when 2
          @db.execute("ALTER TABLE moz_cookies ADD baseDomain TEXT")

          db_prepare("UPDATE moz_cookies SET baseDomain = :baseDomain WHERE id = :id") { |st_update|
            @db.execute("SELECT id, host FROM moz_cookies") { |row|
              domain_name = DomainName.new(row['host'][/\A\.?(.*)/, 1])
              domain = domain_name.domain || domain_name.hostname
              st_update.execute(:baseDomain => domain, :id => row['id'])
            }
          }

          @db.execute("CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)")
          self.schema_version += 1
        when 3
          db_prepare("DELETE FROM moz_cookies WHERE id = :id") { |st_delete|
            prev_row = nil
            @db.execute(                         SELECT id, name, host, path FROM moz_cookies                           ORDER BY name ASC, host ASC, path ASC, expiry ASC) { |row|
              if ]name host path].all? { |col| prev_row and row[col] == prev_row[col] }
                st_delete.execute(prev_row['id'])
              end
              prev_row = row
            }
          }

          @db.execute("ALTER TABLE moz_cookies ADD creationTime INTEGER")
          @db.execute("UPDATE moz_cookies SET creationTime = (SELECT id WHERE id = moz_cookies.id)")
          @db.execute("CREATE UNIQUE INDEX moz_uniqueid ON moz_cookies (name, host, path)")
          self.schema_version += 1
        when 4
          @db.execute("ALTER TABLE moz_cookies RENAME TO moz_cookies_old")
          @db.execute("DROP INDEX moz_basedomain")
          create_table
          @db.execute(                       INSERT INTO moz_cookies                         (baseDomain, appId, inBrowserElement, name, value, host, path, expiry,                          lastAccessed, creationTime, isSecure, isHttpOnly)                         SELECT baseDomain, 0, 0, name, value, host, path, expiry,                                lastAccessed, creationTime, isSecure, isHttpOnly                           FROM moz_cookies_old)
          @db.execute("DROP TABLE moz_cookies_old")
          @logger.info("Upgraded database to schema version %d" % schema_version) if @logger
        else
          break
        end
      }

      begin
        @db.execute("SELECT %s from moz_cookies limit 1" % ALL_COLUMNS.join(', '))
      rescue SQLite3::SQLException
        create_table
      end
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.