use
vars
qw($VERSION @ISA %EXPORT_TAGS @EXPORT @EXPORT_OK)
;
$VERSION
=
'5.32'
;
@ISA
=
qw(Exporter)
;
%EXPORT_TAGS
= (
'all'
=> [
qw(
LoadAll LoadSettings LoadRules ParseParams
DBConnect dbh
ScriptPath ScriptFile
)
]
);
@EXPORT_OK
= ( @{
$EXPORT_TAGS
{
'all'
}} );
@EXPORT
= ( @{
$EXPORT_TAGS
{
'all'
}} );
my
%rules
;
sub
LoadAll {
my
$settings
=
shift
;
LoadSettings(
$settings
);
ParseParams();
DBConnect();
}
sub
LoadSettings {
my
$settings
=
shift
;
$settings
||=
''
;
my
$LOGFILE
=
'audit.log'
;
my
$PHRASEBOOK
=
'phrasebook.ini'
;
my
$PARSEFILE
=
'parserules.ini'
;
my
$host
=
$ENV
{
'HTTP_HOST'
} ||
''
;
my
$ipaddr
=
$ENV
{
'REMOTE_ADDR'
} ||
''
;
my
(
$protocol
) =
$ENV
{
'SERVER_PROTOCOL'
}
? (
$ENV
{
'SERVER_PROTOCOL'
} =~ m!^(\w+)\b!)
:
$ENV
{
'SERVER_PORT'
} &&
$ENV
{
'SERVER_PORT'
} eq
'443'
? (
'https'
)
: (
'http'
);
$protocol
=
lc
(
$protocol
);
my
$path
=
$ENV
{
'REQUEST_URI'
} ?
'REQUEST_URI'
:
'PATH_INFO'
;
my
(
$req
,
$script
) = (
$ENV
{
$path
} &&
$ENV
{
$path
} =~ m|^(.*)/([^?]+)|) ? ($1,$2) : (
''
,
''
);
my
$cgiroot
= (
$req
=~ /^
$protocol
:/) ?
$req
:
$protocol
.
'://'
. (
$ENV
{
'HTTP_HOST'
} ?
$ENV
{
'HTTP_HOST'
} :
''
) .
$req
;
my
$docroot
= (
$req
&&
$cgiroot
=~ m!^((.*)/.*?)! ? $1 :
$cgiroot
);
$cgiroot
=~ s!/$!!;
$docroot
=~ s!/$!!;
my
(
$cgipath
,
$webpath
) = (
$cgiroot
,
$docroot
);
unless
(
$settings
&& -r
$settings
) {
LogError(
"Cannot read settings file [$settings]"
);
SetError(
'ERROR'
,
"Cannot read settings file"
);
return
;
}
my
$cfg
= Config::IniFiles->new(
-file
=>
$settings
);
unless
(
defined
$cfg
) {
LogError(
"Unable to load settings file [$settings]: @Config::IniFiles::errors"
);
SetError(
'ERROR'
,
"Unable to load settings file"
);
return
;
}
for
my
$sect
(
$cfg
->Sections()) {
for
my
$name
(
$cfg
->Parameters(
$sect
)) {
my
@value
=
$cfg
->val(
$sect
,
$name
);
next
unless
(
@value
);
if
(
@value
> 1) {
$settings
{
$name
} = \
@value
;
$tvars
{
$name
} = \
@value
if
(
$sect
=~ /^(PROJECT|HTTP|CMS)$/);
}
elsif
(
@value
== 1) {
$settings
{
$name
} =
$value
[0];
$tvars
{
$name
} =
$value
[0]
if
(
$sect
=~ /^(PROJECT|HTTP|CMS)$/);
}
}
}
$cfg
=
undef
;
SetLogFile(
FILE
=>
$settings
{
'logfile'
},
USER
=>
'labyrinth'
,
LEVEL
=> (
$settings
{
'loglevel'
} || 0),
CLEAR
=> (
defined
$settings
{
'logclear'
} ?
$settings
{
'logclear'
} : 1),
CALLER
=> (
defined
$settings
{
'logcaller'
} ?
$settings
{
'logcaller'
} : 1)
);
$settings
{
'protocol'
} =
$protocol
;
$settings
{
'host'
} =
$host
;
$settings
{
'ipaddr'
} =
$ipaddr
;
$settings
{
'docroot'
} =
$docroot
;
$settings
{
'cgiroot'
} =
$cgiroot
;
$settings
{
'script'
} =
$script
;
$settings
{
'logdir'
} =
"$settings{'webdir'}/cache"
unless
(
$settings
{
'logdir'
});
$settings
{
'config'
} =
"$settings{'cgidir'}/config"
unless
(
$settings
{
'config'
});
$settings
{
'templates'
} =
"$settings{'cgidir'}/templates"
unless
(
$settings
{
'templates'
});
$settings
{
'webpath'
} =
$webpath
unless
(
exists
$settings
{
'webpath'
});
$settings
{
'cgipath'
} =
$cgipath
unless
(
exists
$settings
{
'cgipath'
});
$tvars
{
$_
} =
$settings
{
$_
}
for
(
qw(host docroot cgiroot webpath cgipath script ipaddr)
);
$settings
{
'logfile'
} =
"$settings{'logdir'}/$LOGFILE"
unless
(
$settings
{
'logfile'
});
$settings
{
'phrasebook'
} =
"$settings{'config'}/$PHRASEBOOK"
unless
(
$settings
{
'phrasebook'
});
$settings
{
'parsefile'
} =
"$settings{'config'}/$PARSEFILE"
unless
(
$settings
{
'parsefile'
});
foreach
my
$key
(
qw(logfile phrasebook parsefile)
) {
next
unless
$settings
{
$key
};
next
if
$settings
{
$key
} =~ m|^/|;
$settings
{
$key
} = File::Spec->rel2abs(
$settings
{
$key
} ) ;
}
for
my
$map
(
qw(path title)
) {
next
unless
(
$settings
{
$map
.
'maps'
});
if
(
ref
(
$settings
{
$map
.
'maps'
}) eq
'ARRAY'
) {
for
(@{
$settings
{
$map
.
'maps'
} }) {
my
(
$name
,
$value
) =
split
(/=/,
$_
,2);
$settings
{
$map
.
'map'
}{
$name
} =
$value
;
}
}
elsif
(
$settings
{
$map
.
'maps'
}) {
my
(
$name
,
$value
) =
split
(/=/,
$settings
{
$map
.
'maps'
},2);
$settings
{
$map
.
'map'
}{
$name
} =
$value
;
}
}
Labyrinth::DIUtils::Tool(
$settings
{diutils})
if
(
$settings
{diutils});
$settings
{settingsloaded} = 1;
}
sub
LoadRules {
return
if
(
$settings
{rulesloaded});
my
$rules
=
shift
||
$settings
{
'parsefile'
} ||
''
;
if
(!
$rules
|| !-f
$rules
|| !-r
$rules
) {
LogError(
"Cannot read rules file [$rules]"
);
SetError(
'ERROR'
,
"Cannot read rules file"
);
return
;
}
my
$fh
= IO::File->new(
$rules
,
'r'
);
unless
(
defined
$fh
) {
LogError(
"Cannot open rules file [$rules]: $!"
);
SetError(
'ERROR'
,
"Cannot open rules file"
);
return
;
}
%rules
= (
validator_packages
=> [
qw( Data::FormValidator::Constraints::Upload
Data::FormValidator::Constraints::Words
Labyrinth::Constraints::Emails
Labyrinth::Constraints
Labyrinth::Filters
)
],
filters
=> [
'trim'
, demoroniser()],
msgs
=> {
prefix
=>
'err_'
},
missing_optional_valid
=> 1,
constraint_methods
=> {
realname
=> \
&realname
,
basicwords
=> \
&basicwords
,
simplewords
=> \
&simplewords
,
paragraph
=> \
¶graph
,
emails
=> \
&emails
,
url
=> \
&url
,
ddmmyy
=> \
&ddmmyy
},
);
my
(
$required_regex
,
$optional_regex
);
while
(<
$fh
>) {
s/\s+$//;
my
(
$name
,
$required
,
$default
,
$filters
,
$constraint
,
$regex
) =
split
(
','
,
$_
,6);
next
unless
(
$name
);
$name
=~ s/\s+$//
if
(
defined
$name
);
$required
=~ s/\s+$//
if
(
defined
$required
);
$default
=~ s/\s+$//
if
(
defined
$default
);
$filters
=~ s/\s+$//
if
(
defined
$filters
);
$constraint
=~ s/\s+$//
if
(
defined
$constraint
);
if
(
$name
=~ /^:(.*)/) {
$name
=
qr/$1/
;
if
(
$required
) {
$required_regex
.=
"$name|"
}
else
{
$optional_regex
.=
"$name|"
}
if
(
$constraint
) {
$rules
{constraint_regexp_map}->{
$name
} = _constraint(
$constraint
) }
elsif
(
$regex
) {
$rules
{constraint_regexp_map}->{
$name
} =
qr/^$regex$/
}
else
{
die
"no constraint or regex for entry: $name"
}
if
(
$filters
) {
$rules
{field_filter_regexp_map}->{
$name
} = [
split
(
":"
,
$filters
)] }
}
else
{
if
(
$required
) {
push
@{
$rules
{required}},
$name
}
else
{
push
@{
$rules
{optional}},
$name
}
if
(
$constraint
) {
$rules
{constraints}->{
$name
} = _constraint(
$constraint
) }
elsif
(
$regex
) {
$rules
{constraints}->{
$name
} =
qr/^$regex$/
}
else
{
die
"no constraint or regex for entry: $name"
}
if
(
$default
) {
$rules
{defaults}->{
$name
} =
$default
}
if
(
$filters
) {
$rules
{field_filters}->{
$name
} = [
split
(
":"
,
$filters
)] }
}
}
$fh
->
close
;
if
(
$required_regex
) {
$required_regex
=~ s/|$//;
$rules
{required_regexp} =
qr/^$required_regex$/
;
}
if
(
$optional_regex
) {
$optional_regex
=~ s/|$//;
$rules
{optional_regexp} =
qr/^$optional_regex$/
;
}
$rules
{debug} = 0;
$settings
{rulesloaded} = 1;
}
sub
_constraint {
my
$constraint
=
shift
;
if
(
$constraint
eq
'imagefile'
) {
my
%hash
= (
constraint_method
=>
'file_format'
,
params
=> [
mime_types
=> [
qw!image/jpe image/jpg image/jpeg image/gif image/png!
]],
);
return
\
%hash
;
}
else
{
my
%hash
= (
constraint_method
=>
$constraint
,
);
return
\
%hash
;
}
return
$constraint
;
}
sub
ScriptPath {
return
$settings
{cgipath}
if
(
$settings
{cgipath} =~ m!^http!);
return
$settings
{cgiroot};
}
sub
ScriptFile {
my
%hash
=
@_
;
my
$path
= ScriptPath() ||
''
;
my
$file
=
$hash
{file} ||
$settings
{script};
my
$query
=
$hash
{query} ?
'?'
.
$hash
{query} :
''
;
return
"$path/$file$query"
;
}
sub
DBConnect {
return
$dbi
if
$dbi
;
my
$logfile
=
$settings
{logfile};
my
$phrasebook
=
$settings
{phrasebook};
my
$dictionary
=
$settings
{dictionary};
$dbi
= Labyrinth::DBUtils->new({
driver
=>
$settings
{driver},
database
=>
$settings
{database},
dbfile
=>
$settings
{dbfile},
dbhost
=>
$settings
{dbhost},
dbport
=>
$settings
{dbport},
dbuser
=>
$settings
{dbuser},
dbpass
=>
$settings
{dbpass},
autocommit
=>
$settings
{autocommit},
logfile
=>
$logfile
,
phrasebook
=>
$phrasebook
,
dictionary
=>
$dictionary
,
});
LogDebug(
"DBConnect DONE"
);
$dbi
;
}
sub
_errors {
my
$err
=
shift
;
my
$sql
=
shift
;
my
$message
=
''
;
$message
=
"$err<br />"
if
(
$err
);
$message
.=
"<br />SQL=$sql<br />"
if
(
$sql
);
$message
.=
"ARGS=["
.
join
(
","
,
@_
).
"]"
if
(
@_
);
$tvars
{failures} = [ {
code
=>
'DB'
,
message
=>
$message
} ];
PublishCode(
'MESSAGE'
);
exit
;
}
sub
dbh {
$dbi
|| DBConnect;
}
sub
ParseParams {
LoadRules(
$_
[0])
unless
(
$settings
{rulesloaded});
my
$results
;
if
(!
defined
$ENV
{
'SERVER_SOFTWARE'
}) {
my
$file
=
"$settings{'config'}/cgiparams.nfo"
;
if
(-r
$file
) {
my
$fh
= IO::File->new(
$file
,
'r'
) or
return
;
my
(
%params
,
$params
);
{
local
$/ =
undef
;
$params
= <
$fh
>; }
$fh
->
close
;
foreach
my
$param
(
split
(/[\r\n]+/,
$params
)) {
my
(
$name
,
$value
) =
$param
=~ /(\w+)=(.*)/;
next
unless
(
$name
);
if
(
$value
=~ /\[([^\]]+)\]/) {
@{
$params
{
$name
}} =
split
(
","
,$1);
}
else
{
$params
{
$name
} =
$value
;
}
}
LogDebug(
"params="
.Dumper(\
%params
));
$results
= Data::FormValidator->check(\
%params
, \
%rules
);
$settings
{testing} = 1;
}
}
else
{
my
%fdat
=
$cgi
->Vars;
LogDebug(
"fdat="
.Dumper(\
%fdat
));
for
my
$param
(
grep
{ /^IMAGEUPLOAD/ }
keys
%fdat
) {
if
(
$cgi
->param(
$param
) ) {
CGIFile(
$param
);
$settings
{cgiimages}{
$param
} = 1;
}
$cgi
->
delete
(
$param
)
}
$results
= Data::FormValidator->check(
$cgi
, \
%rules
);
}
if
(
$results
) {
my
$values
=
$results
->valid;
%cgiparams
=
%$values
;
$values
=
$results
->msgs;
foreach
my
$key
(
keys
%$values
) {
$tvars
{
$key
} =
$values
->{
$key
}
if
(
$key
=~ /^err_/);
}
}
else
{
LogDebug(
"NO Data::FormValidator RESULTS!"
);
my
(
$valids
,
$missings
,
$invalids
,
$unknowns
) = Data::FormValidator->validate(
$cgi
, \
%rules
);
LogDebug(
"NO RULE: valids="
. Dumper(
$valids
));
LogDebug(
"NO RULE: invalids="
. Dumper(
$invalids
));
%cgiparams
=
%$valids
;
$cgiparams
{
'err_'
.
$_
} =
'Invalid'
for
(
@$invalids
);
}
$cgiparams
{
$_
} = 1
for
(
keys
%{
$settings
{cgiimages}});
LogDebug(
"cgiparams="
.Dumper(\
%cgiparams
));
LogInfo(
"ParseParams DONE"
);
}
1;