/usr/local/CPAN/deltax-modules/DeltaX/Config.pm
#-----------------------------------------------------------------
package DeltaX::Config;
#-----------------------------------------------------------------
# $Id: Config.pm,v 1.2 2003/10/30 15:51:44 spicak Exp $
#
# (c) DELTA E.S., 2002 - 2003
# This package is free software; you can use it under "Artistic License" from
# Perl.
#-----------------------------------------------------------------
$DeltaX::Config::VERSION = '1.0';
use strict;
use Carp;
#-----------------------------------------------------------------
sub new {
#-----------------------------------------------------------------
# CONSTRUCTOR
#
my $pkg = shift;
my $self = {};
bless ($self, $pkg);
$self->{filename} = '';
$self->{db} = '';
$self->{app} = '';
$self->{db_table} = 'app_lang';
$self->{lang} = 'CZ';
croak ("$pkg created with odd number of parameters - should be of the form option => value")
if (@_ % 2);
for (my $x = 0; $x <= $#_; $x += 2) {
if (exists $self->{$_[$x]}) {
$self->{$_[$x]} = $_[$x+1];
}
else {
$self->{special}{$_[$x]} = $_[$x+1];
}
}
$self->{error} = '';
croak ("$pkg: You must set db handle or filename!")
if (! $self->{filename} and ! $self->{db});
croak ("$pkg: You must set application name for db handle!")
if ($self->{db} and ! $self->{app});
return $self;
}
# END OF new()
#-----------------------------------------------------------------
sub read {
#-----------------------------------------------------------------
#
my $self = shift;
if ($self->{filename}) {
return $self->_read_file();
}
if ($self->{db}) {
return $self->_read_db();
}
return undef;
}
# END OF read()
#-----------------------------------------------------------------
sub _read_file {
#-----------------------------------------------------------------
#
my $self = shift;
local(*INF);
if (! open INF, $self->{filename}) {
$self->{error} = "cannot read file '".$self->{filename}."': $!";
return undef;
}
my %ret;
my $place;
my $prev_line = '';
while (<INF>) {
chomp;
if ($prev_line) {
# zrusime mezery na zacatku
s/^[ \t]*//g;
$_ = $prev_line . ' '. $_;
$prev_line = '';
}
if (! $_) { next; }
if (/^[ ]*#/) {
s/[ ]*#[ ]*//g;
if (/^!(.*)$/) {
my $tmp = $self->_special($1);
return undef unless defined $tmp;
foreach my $key (keys %{$tmp}) {
$ret{$key} = $tmp->{$key} unless exists $ret{$key};
}
}
}
else {
s/#.*$//g;
# zrusime mezery na zacatku a na konci
s/^[ \t]*//g;
s/[ \t]*$//g;
# pokud je nakonci zpetne lomitko, zapamatujeme si to a pridame k
# pristimu radku
if (/\\$/) {
$prev_line = substr($_, 0, -1);
# zrusime mezery na konci
$prev_line =~ s/[ \t]*$//g;
next;
}
my ($key, $val) = split(/=/, $_, 2);
$key = '' if !defined $key;
$val = '' if !defined $val;
$key =~ s/^[ ]*//g;
$key =~ s/[ ]*$//g;
$val =~ s/^[ ]*//g;
$val =~ s/[ ]*$//g;
if (length($key) < 1) { next; }
# untaint!
if ($key =~ /^([-\w.]+)$/) {
$key = $1;
}
else {
$self->{error} = "Invalid key '$key' in file!";
return undef;
}
my $tmp = '$ret{\''.join("'}{'", split(/\./, $key)).'\'}';
$place = eval "\\($tmp)";
$$place = $val;
}
}
close INF;
return \%ret;
}
# END OF _read_file()
#-----------------------------------------------------------------
sub get_error {
#-----------------------------------------------------------------
#
my $self = shift;
return $self->{error};
}
# END OF get_error()
#-----------------------------------------------------------------
sub _special {
#-----------------------------------------------------------------
#
my $self = shift;
my $token = shift;
$token =~ s/^\s*//g;
if ($token =~ /^include/) {
$token =~ /^include\s+(\S+)\s*$/;
return $self->_include($1);
}
if ($token =~ /^import/) {
$token =~ /^import\s+(\S+)\s*$/;
my $tmp = $self->_include($1);
if ($tmp) {
my %tmp;
my $key = $1;
$key = substr($key, 0, rindex($key, '.')) if (rindex($key, '.') > 0);
$tmp{$key} = $tmp;
return \%tmp;
}
else {
return undef;
}
}
$token =~ /^(\S+)\s*(.*)$/s;
my @args;
if ($2) { @args = split(/,/, $2); }
# other special command
if (! exists $self->{special}{$1}) {
$self->{error} = "unknown directive '$1'";
return undef;
}
return $self->{special}{$1}->(@args);
}
# END OF _special
#-----------------------------------------------------------------
sub _include {
#-----------------------------------------------------------------
#
my $self = shift;
my $arg = shift;
# relative path!
if ($arg !~ /^\//) {
if ($self->{filename} =~ /^(.*)\/[^\/]*$/) {
if ($self->{special}{'include'}) {
$arg = $self->{special}{'include'}->($arg);
} else {
$arg = "$1/$arg";
}
}
}
if (!$arg) {
$self->{error} = "include: no file found";
return undef;
}
my @spec;
foreach my $s (sort keys %{$self->{special}}) {
push @spec, $s, $self->{special}{$s};
}
foreach my $s (keys %{$self}) {
push @spec, $s, $self->{$s}
unless ($s eq 'filename' or $s eq 'special' or $s eq 'error');
}
my $inc = new DeltaX::Config(filename=>$arg, @spec);
my $ret = $inc->read();
if (! defined $ret) {
$self->{error} = "include: unable to read '$arg': ". $inc->get_error();
return undef;
}
return $ret;
}
# END OF _include()
#-----------------------------------------------------------------
sub DESTROY {
#-----------------------------------------------------------------
#
my $self = shift;
}
# END OF DESTROY()
1;