Show LoadConfig.pm syntax highlighted
# Config loading routines.
# This object will load a config either from a FILE a SQL DB. Theoretically
# any DB can be used but this has only beed tested with mysql so far.
#
# The 'location' passed to the load() function should either be a filename
# for the config to load or a special "DB" string specifing the DB to connect
# to for the config.
#
# Format of DB string. As you can see it resembles an URL:
# dbtype://user@pass:host/dbname/table/serverid
#
# "dbtype" = DBI identifier for DB, ie: mysql, Pq, Oracle, mSQL, etc...
# "user" = username to connect to DB (can be omitted; pass must be omitted as well)
# "pass" = password to connect to DB (can be omitted)
# "host" = host of DB server (use locahost if server is local, or your DB doesn't use hosts)
# "dbname" = name of database where your table is located (ie: ps_stats)
# "table" = name of table to use to retreive config (ie: config)
# "serverid" = unique string ID for what server info to load from DB ('default' is loaded for all servers)
#
# conftype's:
# main
# langmain
# clantags
# logdata
# logdata_cstrike
# weapon
# weapon_cstrike
# bonus
# bonus_cstrike
# award
# award_cstrike
# theme
#
package LoadConfig;
use strict;
use File::Spec::Functions;
use Carp;
use util;
## Default Paths to search for files
our @INC_PATHS = ();
# this isn't really used, since we're not creating new objects from this package.
# In the future this package might do more. which is why this is here.
sub new {
my ($proto) = @_;
my $class = ref($proto) || $proto;
my $self = {};
$self->{classname} = $class;
bless($self, $class);
return $self;
}
# -----------------------------------------------------------------------------------------------------------------------------
sub load {
my $self = shift;
my %args = (
location => '',
conftype => 'main',
oldconf => undef,
paths => undef,
fatal => 1,
warning => 1,
DBH => undef, # supply a DBI reference, so we dont have to make another connection
@_
);
$args{oldconf} ||= {};
my $conf = $args{oldconf};
if (!exists $args{location} or $args{location} eq '') {
if ($args{fatal} or $args{warning}) {
carp("ERROR: No config location given to LoadConfig->load()");
exit if $args{fatal};
}
}
# convert single path into a 1 element array
$args{paths} = [ $args{paths} || '' ] if !exists $args{paths} or ref $args{paths} ne 'ARRAY';
# if location = mysql://user@pass:localhost/db/table/serverid --- then load config from DB
if ($args{location} =~ /^(\w+):\/\/(?:(.+):)*([^\/]+)\/([^\/]+)\/([^\/]+)(?:\/(.+))*/) {
my ($dbtype, $dbuserpass, $dbhost, $dbname, $dbtable, $srvid) = ($1,$2,$3,$4,$5,$6 || 'default');
my ($dbuser,$dbpass);
if (defined $dbuserpass and $dbuserpass =~ /^([^@]+)@*(.*)/) {
$dbuser = $1;
$dbpass = $2 if defined $2;
}
require DBI;
my $dbh;
$dbh = $args{DBH} || DBI->connect("DBI:$dbtype:database=$dbname;host=$dbhost", $dbuser, $dbpass, {PrintError => 0, RaiseError => 0, AutoCommit => 1});
logerror("Error connecting to database (to read config): " . $DBI::errstr,1) unless ref $dbh;
# get all 'default' options -----
my $cmd = "SELECT var,val FROM $dbtable WHERE conftype='$args{conftype}' AND (srvid='' OR srvid='default')";
%$conf = (%$conf, $self->_getrows($dbh, $cmd));
# get all server specific options (overriding defaults) -----
$cmd = "SELECT var,val FROM $dbtable WHERE conftype='$args{conftype}' AND srvid=" . $dbh->quote($srvid);
%$conf = (%$conf, $self->_getrows($dbh, $cmd));
} else { # load from filename
my $found = '';
my $file = '';
foreach my $path (@{$args{paths}}, @INC_PATHS) {
last if $found;
next if not defined $path;
$file = catfile($path, $args{location});
$found = $file if -r $file;
}
# default to normal file name if nothing was found
$file = $found || (($args{paths}[0]) ? catfile($args{paths}[0], $args{location}) : $args{location});
my %a = %args;
$a{filename} = $file;
%$conf = loadconfig(%a);
# %$conf = loadconfig(filename => $file, oldconf => $args{oldconf}, fatal => $args{fatal}, warning => $args{warning});
}
return wantarray ? %$conf : $conf;
}
# -----------------------------------------------------------------------------------------------------------------------------
# fetches the config rows from the DB
sub _getrows {
my $self = shift;
my $dbh = shift;
my $cmd = shift;
my $sth = $dbh->prepare($cmd);
my $idx = 1;
my %conf = ();
$sth->execute() or logerror("Error reading config from database: " . $dbh->errstr,1);
while (my ($var,$val) = $sth->fetchrow_array) {
$var = lc $var;
if ($var =~ /^(\S+)\.([\w\d]+)/) {
my $section = $1;
$var = $2;
unless (exists $conf{$section}) { # mimic's the file loading routines, to keep track of 'sections' in the config
$conf{$section}{IDX} = $idx++;
$conf{$section}{SECTION} = $1;
}
$conf{$section}{$var} = $val;
} else {
$conf{$var} = $val;
}
}
return wantarray ? %conf : \%conf;
}
# -----------------------------------------------------------------------------------------------------------------------------
# Add 1 or more paths to GLOBAL array
sub ADDPATH {
my $self = shift;
while (my $path = shift @_) {
if (-d $path) { # make sure path exists
return unshift(@INC_PATHS, $path); # add it to array
} else {
# warn "Ignoring invalid path: $path";
return 0;
}
}
}
# -----------------------------------------------------------------------------------------------------------------------------
# returns the GLOBAL @INC_PATHS array (or a reference to it if called in scalar context)
sub PATH() {
wantarray ? @INC_PATHS : \@INC_PATHS;
}
# -----------------------------------------------------------------------------------------------------------------------------
# Destructor method.
sub DESTROY { }
return 1;
See more files for this project here