class DBI::DBRC

The DBRC class encapsulates a database resource config file.

Constants

VERSION

The version of the dbi-dbrc library

WINDOWS
YAML

Attributes

database[RW]

The database or host to be connected to.

db[RW]

The database or host to be connected to.

db=[RW]

The database or host to be connected to.

dbrc_dir[RW]

The directory where the .dbrc file is stored.

dbrc_file[RW]

The full path to the .dbrc file.

driver[RW]

The driver associated with the database. This is used to internally to construct the DSN.

dsn[RW]

Data source name, e.g. “dbi:OCI8:your_database”.

host[RW]

The database or host to be connected to.

host=[RW]

The database or host to be connected to.

interval[RW]

The interval, in seconds, between each connection attempt.

max_reconn[RW]

The maximum number of reconnects a program should make before giving up.

max_reconn=[RW]

The maximum number of reconnects a program should make before giving up.

maximum_reconnects[RW]

The maximum number of reconnects a program should make before giving up.

passwd[RW]

The password associated with the database or host.

passwd=[RW]

The password associated with the database or host.

password[RW]

The password associated with the database or host.

time_out[RW]

The timeout, in seconds, for each connection attempt.

time_out=[RW]

The timeout, in seconds, for each connection attempt.

timeout[RW]

The timeout, in seconds, for each connection attempt.

user[RW]

The user name used for the database or host connection.

Public Class Methods

new(database, user = nil, dbrc_dir = Dir.home, gpg_options = nil) click to toggle source

Returns a new DBI::DBRC object. The contents of the object depend on the arguments passed to the constructor. If only a database name is passed, then the first entry found in the .dbrc file that matches that database is parsed. If a user name is also included, then the first entry that matches both the database and user name is parsed.

If a directory is passed as the third argument, then DBRC will look in that directory, instead of the default directory, for the .dbrc file.

If an entry cannot be found for the database, or database plus user combination, then a Error is raised. If the .dbrc file cannot be found, or is setup improperly with regards to permissions or properties then a DBI::DBRC::Error is raised.

See the README for the rules regarding .dbrc files and permissions.

Note that this library can also be used as a general password storage mechanism. In that case simply treat the 'database' as the host name, and ignore the DBI::DBRC#dsn and DBI::DBRC#driver methods.

On unixy systems you can GPG encrypt the file, and this library will decrypt it for you based on the gpg_options that you pass.

Examples:

# Find the first match for 'some_database'
DBI::DBRC.new('some_database')

# Find the first match for 'foo_user@some_database'
DBI::DBRC.new('some_database', 'foo_user')

# Find the first match for 'foo_user@some_database' under /usr/local
DBI::DBRC.new('some_database', 'foo_usr', '/usr/local')

# Pass along a GPG password to decrypt the file.
DBI::DBRC.new('some_database', 'foo_usr', '/usr/local', :gpg_options => {:password => 'xxx'})
# File lib/dbi/dbrc.rb, line 107
def initialize(database, user = nil, dbrc_dir = Dir.home, gpg_options = nil)
  if dbrc_dir.nil?
    # Default to the app data directory on Windows, or root on Unix, if
    # no home dir can be found.
    if home.nil?
      if WINDOWS
        home = Dir::APPDATA
      else
        home = '/'
      end
    end

    @dbrc_file = File.join(home, '.dbrc')
    dbrc_dir = home
  else
    raise Error, 'bad directory' unless File.directory?(dbrc_dir)
    @dbrc_file = File.join(dbrc_dir, '.dbrc')
  end

  @dbrc_dir  = dbrc_dir
  @database  = database
  @user      = user

  file_was_encrypted = false # Win32 only

  @driver   = nil
  @interval = nil
  @timeout  = nil
  @maximum_reconnects = nil

  check_file()

  # Decrypt and re-encrypt the file if we're on MS Windows and the
  # file is encrypted.
  begin
    if WINDOWS && File.encrypted?(@dbrc_file)
      file_was_encrypted = true
      File.decrypt(@dbrc_file)
    end

    if gpg_options
      require 'gpgme'
      require 'stringio'
      crypto = GPGME::Crypto.new(gpg_options)
      stringio = crypto.decrypt(File.open(@dbrc_file))
      parse_dbrc_config_file(StringIO.new(stringio.read))
    else
      parse_dbrc_config_file
    end

    validate_data
    convert_numeric_strings
    create_dsn_string
  ensure
    File.encrypt(@dbrc_file) if WINDOWS && file_was_encrypted
  end
end

Public Instance Methods

inspect() click to toggle source

Inspection of the DBI::DBRC object. This is identical to the standard Ruby Object#inspect, except that the password field is filtered.

# File lib/dbi/dbrc.rb, line 168
def inspect
  str = instance_variables.map do |iv|
    if iv == '@password'
      "#{iv}=[FILTERED]"
    else
      "#{iv}=#{instance_variable_get(iv).inspect}"
    end
  end.join(', ')

  "#<#{self.class}:0x#{(object_id * 2).to_s(16)} " + str + '>'
end

Private Instance Methods

check_file(file = @dbrc_file) click to toggle source

Check ownership and permissions

# File lib/dbi/dbrc.rb, line 201
def check_file(file = @dbrc_file)
  File.open(file) do |f|
    # Permissions must be set to 600 or better on Unix systems.
    # Must be hidden on Win32 systems.
    if WINDOWS
      raise Error, 'The .dbrc file must be hidden' unless File.hidden?(file)
    else
      raise Error, 'Bad .dbrc file permissions' unless (f.stat.mode & 0o77) == 0
    end

    # Only the owner may use it
    raise Error, 'Not owner of .dbrc file' unless f.stat.owned?
  end
end
convert_numeric_strings() click to toggle source

Converts strings that should be numbers into actual numbers

# File lib/dbi/dbrc.rb, line 189
def convert_numeric_strings
  @interval   = @interval.to_i if @interval
  @timeout    = @timeout.to_i if @timeout
  @maximum_reconnects = @maximum_reconnects.to_i if @maximum_reconnects
end
create_dsn_string() click to toggle source

Create the dsn string if the driver is defined

# File lib/dbi/dbrc.rb, line 196
def create_dsn_string
  @dsn = "dbi:#{@driver}:#{@database}" if @driver
end
parse_dbrc_config_file(file = @dbrc_file) click to toggle source

Parse the text out of the .dbrc file. This is the only method you need to redefine if writing your own config handler.

# File lib/dbi/dbrc.rb, line 218
def parse_dbrc_config_file(file = @dbrc_file)
  begin
    fh = file.is_a?(StringIO) ? file : File.open(file)

    fh.each_line do |line|
      next if line =~ /^#/ # Ignore comments
      db, user, pwd, driver, timeout, max, interval = line.split

      next unless @database == db
      next if @user && @user != user

      @user               = user
      @password           = pwd
      @driver             = driver
      @timeout            = timeout
      @maximum_reconnects = max
      @interval           = interval
      break
    end
  ensure
    fh.close if fh && fh.respond_to?(:close)
  end

  if @user
    raise Error, "no record found for #{@user}@#{@database}" unless @user
  else
    raise Error, "no record found for #{@database}" unless @database
  end
end
validate_data() click to toggle source

Ensure that the user/password has been set

# File lib/dbi/dbrc.rb, line 183
def validate_data
  raise Error, "no user found associated with #{@database}" unless @user
  raise Error, "password not defined for #{@user}@#{@database}" unless @password
end