a65af9c8b3
Namespaced everything under Msf::Db::PostgreSQL, renamed top-level include to postgres_msf to disambiguate. Included recursive requires for all files. Noted the IO monkeypatch -- should revisit. Added a testcase for database connections. The reason for the namespacing is to avoid stomping on any existing Postgres-PR installations, or any other requires named "postgres" or "postgresql" or even "pg," since these may or may not support the method's we're using here. The seperate namespace also allows for easier integration of custom commands later on. git-svn-id: file:///home/svn/framework3/trunk@8342 4d416f70-5f16-0410-b530-b9f4589650da
162 lines
2.4 KiB
Ruby
162 lines
2.4 KiB
Ruby
# This is a compatibility layer for using the pure Ruby postgres-pr instead of
|
|
# the C interface of postgres.
|
|
|
|
require 'postgres_msf'
|
|
require 'postgres/postgres-pr/connection'
|
|
|
|
# Namespace for Metasploit branch.
|
|
module Msf
|
|
module Db
|
|
|
|
class PGconn
|
|
class << self
|
|
alias connect new
|
|
end
|
|
|
|
def initialize(host, port, options, tty, database, user, auth)
|
|
uri =
|
|
if host.nil?
|
|
nil
|
|
elsif host[0] != ?/
|
|
"tcp://#{ host }:#{ port }"
|
|
else
|
|
"unix:#{ host }/.s.PGSQL.#{ port }"
|
|
end
|
|
@host = host
|
|
@db = database
|
|
@user = user
|
|
@conn = PostgresPR::Connection.new(database, user, auth, uri)
|
|
end
|
|
|
|
def close
|
|
@conn.close
|
|
end
|
|
|
|
attr_reader :host, :db, :user
|
|
|
|
def query(sql)
|
|
PGresult.new(@conn.query(sql))
|
|
end
|
|
|
|
alias exec query
|
|
|
|
def transaction_status
|
|
@conn.transaction_status
|
|
end
|
|
|
|
def self.escape(str)
|
|
str.gsub("'","''").gsub("\\", "\\\\\\\\")
|
|
end
|
|
|
|
def notice_processor
|
|
@conn.notice_processor
|
|
end
|
|
|
|
def notice_processor=(np)
|
|
@conn.notice_processor = np
|
|
end
|
|
|
|
def self.quote_ident(name)
|
|
%("#{name}")
|
|
end
|
|
|
|
end
|
|
|
|
class PGresult
|
|
include Enumerable
|
|
|
|
EMPTY_QUERY = 0
|
|
COMMAND_OK = 1
|
|
TUPLES_OK = 2
|
|
COPY_OUT = 3
|
|
COPY_IN = 4
|
|
BAD_RESPONSE = 5
|
|
NONFATAL_ERROR = 6
|
|
FATAL_ERROR = 7
|
|
|
|
def each(&block)
|
|
@result.each(&block)
|
|
end
|
|
|
|
def [](index)
|
|
@result[index]
|
|
end
|
|
|
|
def initialize(res)
|
|
@res = res
|
|
@fields = @res.fields.map {|f| f.name}
|
|
@result = @res.rows
|
|
end
|
|
|
|
# TODO: status, getlength, cmdstatus
|
|
|
|
attr_reader :result, :fields
|
|
|
|
def num_tuples
|
|
@result.size
|
|
end
|
|
|
|
def num_fields
|
|
@fields.size
|
|
end
|
|
|
|
def fieldname(index)
|
|
@fields[index]
|
|
end
|
|
|
|
def fieldnum(name)
|
|
@fields.index(name)
|
|
end
|
|
|
|
def type(index)
|
|
# TODO: correct?
|
|
@res.fields[index].type_oid
|
|
end
|
|
|
|
def size(index)
|
|
raise
|
|
# TODO: correct?
|
|
@res.fields[index].typlen
|
|
end
|
|
|
|
def getvalue(tup_num, field_num)
|
|
@result[tup_num][field_num]
|
|
end
|
|
|
|
def status
|
|
if num_tuples > 0
|
|
TUPLES_OK
|
|
else
|
|
COMMAND_OK
|
|
end
|
|
end
|
|
|
|
def cmdstatus
|
|
@res.cmd_tag || ''
|
|
end
|
|
|
|
# free the result set
|
|
def clear
|
|
@res = @fields = @result = nil
|
|
end
|
|
|
|
# Returns the number of rows affected by the SQL command
|
|
def cmdtuples
|
|
case @res.cmd_tag
|
|
when nil
|
|
return nil
|
|
when /^INSERT\s+(\d+)\s+(\d+)$/, /^(DELETE|UPDATE|MOVE|FETCH)\s+(\d+)$/
|
|
$2.to_i
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
class PGError < Exception
|
|
end
|
|
|
|
end
|
|
end
|