| blib/lib/Labyrinth/Globals.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 10 | 12 | 83.3 |
| branch | n/a | ||
| condition | n/a | ||
| subroutine | 4 | 4 | 100.0 |
| pod | n/a | ||
| total | 14 | 16 | 87.5 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Labyrinth::Globals; | ||||||
| 2 | |||||||
| 3 | 8 | 8 | 37 | use warnings; | |||
| 8 | 10 | ||||||
| 8 | 283 | ||||||
| 4 | 8 | 8 | 31 | use strict; | |||
| 8 | 11 | ||||||
| 8 | 273 | ||||||
| 5 | |||||||
| 6 | 8 | 8 | 94 | use vars qw($VERSION @ISA %EXPORT_TAGS @EXPORT @EXPORT_OK); | |||
| 8 | 10 | ||||||
| 8 | 1000 | ||||||
| 7 | $VERSION = '5.30'; | ||||||
| 8 | |||||||
| 9 | =head1 NAME | ||||||
| 10 | |||||||
| 11 | Labyrinth::Globals - Configuration and Parameter Handler for Labyrinth | ||||||
| 12 | |||||||
| 13 | =head1 SYNOPSIS | ||||||
| 14 | |||||||
| 15 | use Labyrinth::Globals qw(:all); | ||||||
| 16 | |||||||
| 17 | # database object creation | ||||||
| 18 | DBConnect(); | ||||||
| 19 | |||||||
| 20 | # Interface (CGI) parameter handling | ||||||
| 21 | ParseParams(); | ||||||
| 22 | |||||||
| 23 | =head1 DESCRIPTION | ||||||
| 24 | |||||||
| 25 | The Globals package contains a number of variables and functions that are | ||||||
| 26 | used across the system. The variables contain input and output values, | ||||||
| 27 | and the functions are generic. | ||||||
| 28 | |||||||
| 29 | =head1 EXPORT | ||||||
| 30 | |||||||
| 31 | All by default. | ||||||
| 32 | |||||||
| 33 | use Labyrinth::Globals qw(:all); # all methods | ||||||
| 34 | |||||||
| 35 | =cut | ||||||
| 36 | |||||||
| 37 | # ------------------------------------- | ||||||
| 38 | # Export Details | ||||||
| 39 | |||||||
| 40 | require Exporter; | ||||||
| 41 | @ISA = qw(Exporter); | ||||||
| 42 | |||||||
| 43 | %EXPORT_TAGS = ( | ||||||
| 44 | 'all' => [ qw( | ||||||
| 45 | LoadAll LoadSettings LoadRules ParseParams | ||||||
| 46 | DBConnect dbh | ||||||
| 47 | ScriptPath ScriptFile | ||||||
| 48 | ) ] | ||||||
| 49 | ); | ||||||
| 50 | |||||||
| 51 | @EXPORT_OK = ( @{$EXPORT_TAGS{'all'}} ); | ||||||
| 52 | @EXPORT = ( @{$EXPORT_TAGS{'all'}} ); | ||||||
| 53 | |||||||
| 54 | # ------------------------------------- | ||||||
| 55 | # Library Modules | ||||||
| 56 | |||||||
| 57 | 8 | 8 | 7177 | use Config::IniFiles; | |||
| 0 | |||||||
| 0 | |||||||
| 58 | use Data::Dumper; | ||||||
| 59 | use Data::FormValidator; | ||||||
| 60 | use Data::FormValidator::Constraints::Upload; | ||||||
| 61 | use Data::FormValidator::Constraints::Words; | ||||||
| 62 | use Data::FormValidator::Filters::Demoroniser qw(demoroniser); | ||||||
| 63 | use File::Basename; | ||||||
| 64 | use File::Path; | ||||||
| 65 | use File::Spec::Functions; | ||||||
| 66 | use IO::File; | ||||||
| 67 | |||||||
| 68 | use Labyrinth::Audit; | ||||||
| 69 | use Labyrinth::Constraints; | ||||||
| 70 | use Labyrinth::Constraints::Emails; | ||||||
| 71 | use Labyrinth::DBUtils; | ||||||
| 72 | use Labyrinth::DIUtils; | ||||||
| 73 | use Labyrinth::Filters qw(float2 float3 float5); | ||||||
| 74 | use Labyrinth::Media; | ||||||
| 75 | use Labyrinth::Variables; | ||||||
| 76 | use Labyrinth::Writer; | ||||||
| 77 | |||||||
| 78 | # ------------------------------------- | ||||||
| 79 | # Variables | ||||||
| 80 | |||||||
| 81 | my %rules; # internal rules hash | ||||||
| 82 | |||||||
| 83 | # ------------------------------------- | ||||||
| 84 | # The Subs | ||||||
| 85 | |||||||
| 86 | =head1 FUNCTIONS | ||||||
| 87 | |||||||
| 88 | =head2 Loaders | ||||||
| 89 | |||||||
| 90 | =over 4 | ||||||
| 91 | |||||||
| 92 | =item LoadAll([$dir]) | ||||||
| 93 | |||||||
| 94 | LoadAll() automatically loads and instatiates many global variables. The | ||||||
| 95 | method assumes default values are required. Can be called with a base install | ||||||
| 96 | directory path, which is then used by LoadSettings(). | ||||||
| 97 | |||||||
| 98 | This method should be called at the beginning of any script. | ||||||
| 99 | |||||||
| 100 | =item LoadSettings($dir) | ||||||
| 101 | |||||||
| 102 | LoadSettings() loads a settings file (config/settings.ini) and stores them | ||||||
| 103 | in an internal hash. Typical settings are database settings (eq driver, | ||||||
| 104 | database, user, password) and general settings (eg administrator email). | ||||||
| 105 | |||||||
| 106 | LoadSettings() can be passed the name of the base install directory, or it will | ||||||
| 107 | attempt to figure it out via the current working directory. | ||||||
| 108 | |||||||
| 109 | =item LoadRules() | ||||||
| 110 | |||||||
| 111 | LoadRules() loads a rules file (default is parserules.ini or the name of the | ||||||
| 112 | 'parsefile' in the settings configuration file) and store the rules in an | ||||||
| 113 | internal hash. This hash is then used to verify the contains of any interface | ||||||
| 114 | (CGI) parameters passed to the script. | ||||||
| 115 | |||||||
| 116 | Note that as LoadRules() can be called many times with different rules | ||||||
| 117 | files, only the last value of a given rule is stored. This is useful if | ||||||
| 118 | you wish to have a standard rules file and wish to load further or | ||||||
| 119 | different rules dependant upon the script being used. | ||||||
| 120 | |||||||
| 121 | =back | ||||||
| 122 | |||||||
| 123 | =cut | ||||||
| 124 | |||||||
| 125 | sub LoadAll { | ||||||
| 126 | my $settings = shift; | ||||||
| 127 | |||||||
| 128 | LoadSettings($settings); | ||||||
| 129 | ParseParams(); | ||||||
| 130 | DBConnect(); | ||||||
| 131 | } | ||||||
| 132 | |||||||
| 133 | sub LoadSettings { | ||||||
| 134 | my $settings = shift; | ||||||
| 135 | $settings ||= ''; | ||||||
| 136 | |||||||
| 137 | # default file names | ||||||
| 138 | my $LOGFILE = 'audit.log'; | ||||||
| 139 | my $PHRASEBOOK = 'phrasebook.ini'; | ||||||
| 140 | my $PARSEFILE = 'parserules.ini'; | ||||||
| 141 | |||||||
| 142 | #print STDERR "# ENV $_ => $ENV{$_}\n" for('HTTP_HOST', 'REMOTE_ADDR', 'SERVER_PROTOCOL', 'SERVER_PORT'); | ||||||
| 143 | # Server/HTTP values | ||||||
| 144 | my $host = $ENV{'HTTP_HOST'} || ''; | ||||||
| 145 | my $ipaddr = $ENV{'REMOTE_ADDR'} || ''; | ||||||
| 146 | my ($protocol) = $ENV{'SERVER_PROTOCOL'} | ||||||
| 147 | ? ($ENV{'SERVER_PROTOCOL'} =~ m!^(\w+)\b!) | ||||||
| 148 | : $ENV{'SERVER_PORT'} && $ENV{'SERVER_PORT'} eq '443' | ||||||
| 149 | ? ('https') | ||||||
| 150 | : ('http'); | ||||||
| 151 | $protocol = lc($protocol); | ||||||
| 152 | |||||||
| 153 | my $path = $ENV{'REQUEST_URI'} ? 'REQUEST_URI' : 'PATH_INFO'; | ||||||
| 154 | my ($req,$script) = ($ENV{$path} && $ENV{$path} =~ m|^(.*)/([^?]+)|) ? ($1,$2) : ('',''); | ||||||
| 155 | my $cgiroot = ($req =~ /^$protocol:/) ? $req : $protocol . '://' . ($ENV{'HTTP_HOST'} ? $ENV{'HTTP_HOST'} : '') . $req; | ||||||
| 156 | my $docroot = ($req && $cgiroot =~ m!^((.*)/.*?)! ? $1 : $cgiroot); | ||||||
| 157 | $cgiroot =~ s!/$!!; | ||||||
| 158 | $docroot =~ s!/$!!; | ||||||
| 159 | |||||||
| 160 | # set defaults | ||||||
| 161 | my ($cgipath,$webpath) = ($cgiroot,$docroot); | ||||||
| 162 | |||||||
| 163 | # load the configuration data | ||||||
| 164 | unless($settings && -r $settings) { | ||||||
| 165 | LogError("Cannot read settings file [$settings]"); | ||||||
| 166 | SetError('ERROR',"Cannot read settings file"); | ||||||
| 167 | return; | ||||||
| 168 | } | ||||||
| 169 | |||||||
| 170 | my $cfg = Config::IniFiles->new( -file => $settings ); | ||||||
| 171 | unless(defined $cfg) { | ||||||
| 172 | LogError("Unable to load settings file [$settings]: @Config::IniFiles::errors"); | ||||||
| 173 | SetError('ERROR',"Unable to load settings file"); | ||||||
| 174 | return; | ||||||
| 175 | } | ||||||
| 176 | |||||||
| 177 | # load the configuration data | ||||||
| 178 | for my $sect ($cfg->Sections()) { | ||||||
| 179 | for my $name ($cfg->Parameters($sect)) { | ||||||
| 180 | my @value = $cfg->val($sect,$name); | ||||||
| 181 | next unless(@value); | ||||||
| 182 | if(@value > 1) { | ||||||
| 183 | $settings{$name} = \@value; | ||||||
| 184 | $tvars{$name} = \@value if($sect =~ /^(PROJECT|HTTP|CMS)$/); | ||||||
| 185 | } elsif(@value == 1) { | ||||||
| 186 | $settings{$name} = $value[0]; | ||||||
| 187 | $tvars{$name} = $value[0] if($sect =~ /^(PROJECT|HTTP|CMS)$/); | ||||||
| 188 | } | ||||||
| 189 | } | ||||||
| 190 | } | ||||||
| 191 | $cfg = undef; | ||||||
| 192 | |||||||
| 193 | SetLogFile( FILE => $settings{'logfile'}, | ||||||
| 194 | USER => 'labyrinth', | ||||||
| 195 | LEVEL => ($settings{'loglevel'} || 0), | ||||||
| 196 | CLEAR => (defined $settings{'logclear'} ? $settings{'logclear'} : 1), | ||||||
| 197 | CALLER => (defined $settings{'logcaller'} ? $settings{'logcaller'} : 1) | ||||||
| 198 | ); | ||||||
| 199 | |||||||
| 200 | # evaluate standard path settings | ||||||
| 201 | $settings{'protocol'} = $protocol; | ||||||
| 202 | $settings{'host'} = $host; | ||||||
| 203 | $settings{'ipaddr'} = $ipaddr; | ||||||
| 204 | $settings{'docroot'} = $docroot; | ||||||
| 205 | $settings{'cgiroot'} = $cgiroot; | ||||||
| 206 | $settings{'script'} = $script; | ||||||
| 207 | $settings{'logdir'} = "$settings{'webdir'}/cache" unless($settings{'logdir'}); | ||||||
| 208 | $settings{'config'} = "$settings{'cgidir'}/config" unless($settings{'config'}); | ||||||
| 209 | $settings{'templates'} = "$settings{'cgidir'}/templates" unless($settings{'templates'}); | ||||||
| 210 | $settings{'webpath'} = $webpath unless(exists $settings{'webpath'}); | ||||||
| 211 | $settings{'cgipath'} = $cgipath unless(exists $settings{'cgipath'}); | ||||||
| 212 | |||||||
| 213 | $tvars{$_} = $settings{$_} for(qw(host docroot cgiroot webpath cgipath script ipaddr)); | ||||||
| 214 | |||||||
| 215 | $settings{'logfile'} = "$settings{'logdir'}/$LOGFILE" unless($settings{'logfile'}); | ||||||
| 216 | $settings{'phrasebook'} = "$settings{'config'}/$PHRASEBOOK" unless($settings{'phrasebook'}); | ||||||
| 217 | $settings{'parsefile'} = "$settings{'config'}/$PARSEFILE" unless($settings{'parsefile'}); | ||||||
| 218 | |||||||
| 219 | # generate the absolute path, in the event of errors | ||||||
| 220 | foreach my $key (qw(logfile phrasebook parsefile)) { | ||||||
| 221 | next unless $settings{$key}; | ||||||
| 222 | next if $settings{$key} =~ m|^/|; | ||||||
| 223 | $settings{$key} = File::Spec->rel2abs( $settings{$key} ) ; | ||||||
| 224 | } | ||||||
| 225 | |||||||
| 226 | # path & title mappings | ||||||
| 227 | for my $map (qw(path title)) { | ||||||
| 228 | next unless($settings{$map . 'maps'}); | ||||||
| 229 | if( ref($settings{$map . 'maps'}) eq 'ARRAY') { | ||||||
| 230 | for(@{ $settings{$map . 'maps'} }) { | ||||||
| 231 | my ($name,$value) = split(/=/,$_,2); | ||||||
| 232 | $settings{$map . 'map'}{$name} = $value; | ||||||
| 233 | } | ||||||
| 234 | } elsif($settings{$map . 'maps'}) { | ||||||
| 235 | my ($name,$value) = split(/=/,$settings{$map . 'maps'},2); | ||||||
| 236 | $settings{$map . 'map'}{$name} = $value; | ||||||
| 237 | } | ||||||
| 238 | } | ||||||
| 239 | |||||||
| 240 | #LogDebug("settings=".Dumper(\%settings)); | ||||||
| 241 | |||||||
| 242 | # set image processing driver, if specified | ||||||
| 243 | Labyrinth::DIUtils::Tool($settings{diutils}) if($settings{diutils}); | ||||||
| 244 | |||||||
| 245 | $settings{settingsloaded} = 1; | ||||||
| 246 | } | ||||||
| 247 | |||||||
| 248 | sub LoadRules { | ||||||
| 249 | return if($settings{rulesloaded}); | ||||||
| 250 | |||||||
| 251 | # ensure we can access the rules file | ||||||
| 252 | my $rules = shift || $settings{'parsefile'} || ''; | ||||||
| 253 | if(!$rules || !-f $rules || !-r $rules) { | ||||||
| 254 | LogError("Cannot read rules file [$rules]"); | ||||||
| 255 | SetError('ERROR',"Cannot read rules file"); | ||||||
| 256 | return; | ||||||
| 257 | } | ||||||
| 258 | |||||||
| 259 | my $fh = IO::File->new($rules, 'r'); | ||||||
| 260 | unless(defined $fh) { | ||||||
| 261 | LogError("Cannot open rules file [$rules]: $!"); | ||||||
| 262 | SetError('ERROR',"Cannot open rules file"); | ||||||
| 263 | return; | ||||||
| 264 | } | ||||||
| 265 | |||||||
| 266 | %rules = ( | ||||||
| 267 | validator_packages => [qw( Data::FormValidator::Constraints::Upload | ||||||
| 268 | Data::FormValidator::Constraints::Words | ||||||
| 269 | Labyrinth::Constraints::Emails | ||||||
| 270 | Labyrinth::Constraints | ||||||
| 271 | Labyrinth::Filters | ||||||
| 272 | )], | ||||||
| 273 | filters => ['trim', demoroniser()], | ||||||
| 274 | msgs => {prefix=> 'err_'}, # set a custom error prefix | ||||||
| 275 | # untaint_all_constraints => 1, | ||||||
| 276 | missing_optional_valid => 1, | ||||||
| 277 | constraint_methods => { | ||||||
| 278 | realname => \&realname, | ||||||
| 279 | basicwords => \&basicwords, | ||||||
| 280 | simplewords => \&simplewords, | ||||||
| 281 | paragraph => \¶graph, | ||||||
| 282 | emails => \&emails, | ||||||
| 283 | url => \&url, | ||||||
| 284 | ddmmyy => \&ddmmyy | ||||||
| 285 | }, | ||||||
| 286 | ); | ||||||
| 287 | |||||||
| 288 | my ($required_regex,$optional_regex); | ||||||
| 289 | |||||||
| 290 | while(<$fh>) { | ||||||
| 291 | s/\s+$//; | ||||||
| 292 | |||||||
| 293 | my ($name,$required,$default,$filters,$constraint,$regex) = split(',',$_,6); | ||||||
| 294 | next unless($name); | ||||||
| 295 | |||||||
| 296 | $name =~ s/\s+$// if(defined $name); | ||||||
| 297 | $required =~ s/\s+$// if(defined $required); | ||||||
| 298 | $default =~ s/\s+$// if(defined $default); | ||||||
| 299 | $filters =~ s/\s+$// if(defined $filters); | ||||||
| 300 | $constraint =~ s/\s+$// if(defined $constraint); | ||||||
| 301 | |||||||
| 302 | # $rules{$name}->{required} = $required; | ||||||
| 303 | # $rules{$name}->{default} = $default; | ||||||
| 304 | # $rules{$name}->{constraint} = $constraint; | ||||||
| 305 | # $rules{$name}->{regex} = "@regex"; | ||||||
| 306 | |||||||
| 307 | if($name =~ /^:(.*)/) { | ||||||
| 308 | $name = qr/$1/; | ||||||
| 309 | if($required) { $required_regex .= "$name|" } | ||||||
| 310 | else { $optional_regex .= "$name|" } | ||||||
| 311 | if($constraint) { $rules{constraint_regexp_map}->{$name} = _constraint($constraint) } | ||||||
| 312 | elsif($regex) { $rules{constraint_regexp_map}->{$name} = qr/^$regex$/ } | ||||||
| 313 | else { die "no constraint or regex for entry: $name" } | ||||||
| 314 | if($filters) { $rules{field_filter_regexp_map}->{$name} = [split(":",$filters)] } | ||||||
| 315 | } else { | ||||||
| 316 | if($required) { push @{$rules{required}}, $name } | ||||||
| 317 | else { push @{$rules{optional}}, $name } | ||||||
| 318 | if($constraint) { $rules{constraints}->{$name} = _constraint($constraint) } | ||||||
| 319 | elsif($regex) { $rules{constraints}->{$name} = qr/^$regex$/ } | ||||||
| 320 | else { die "no constraint or regex for entry: $name" } | ||||||
| 321 | if($default) { $rules{defaults}->{$name} = $default } | ||||||
| 322 | if($filters) { $rules{field_filters}->{$name} = [split(":",$filters)] } | ||||||
| 323 | } | ||||||
| 324 | } | ||||||
| 325 | $fh->close; | ||||||
| 326 | |||||||
| 327 | #LogDebug("Constraints: rules=" . Dumper(\%rules)); | ||||||
| 328 | |||||||
| 329 | if($required_regex) { | ||||||
| 330 | $required_regex =~ s/|$//; | ||||||
| 331 | $rules{required_regexp} = qr/^$required_regex$/; | ||||||
| 332 | } | ||||||
| 333 | |||||||
| 334 | if($optional_regex) { | ||||||
| 335 | $optional_regex =~ s/|$//; | ||||||
| 336 | $rules{optional_regexp} = qr/^$optional_regex$/; | ||||||
| 337 | } | ||||||
| 338 | |||||||
| 339 | $rules{debug} = 0; | ||||||
| 340 | |||||||
| 341 | $settings{rulesloaded} = 1; | ||||||
| 342 | } | ||||||
| 343 | |||||||
| 344 | sub _constraint { | ||||||
| 345 | my $constraint = shift; | ||||||
| 346 | if($constraint eq 'imagefile') { | ||||||
| 347 | my %hash = ( | ||||||
| 348 | constraint_method => 'file_format', | ||||||
| 349 | params => [mime_types => [qw!image/jpe image/jpg image/jpeg image/gif image/png!]], | ||||||
| 350 | ); | ||||||
| 351 | return \%hash; | ||||||
| 352 | } else { | ||||||
| 353 | my %hash = ( | ||||||
| 354 | constraint_method => $constraint, | ||||||
| 355 | ); | ||||||
| 356 | return \%hash; | ||||||
| 357 | } | ||||||
| 358 | |||||||
| 359 | return $constraint; | ||||||
| 360 | } | ||||||
| 361 | |||||||
| 362 | =head2 Script Name | ||||||
| 363 | |||||||
| 364 | =over 4 | ||||||
| 365 | |||||||
| 366 | =item ScriptPath() | ||||||
| 367 | |||||||
| 368 | =item ScriptFile() | ||||||
| 369 | |||||||
| 370 | =back | ||||||
| 371 | |||||||
| 372 | =cut | ||||||
| 373 | |||||||
| 374 | sub ScriptPath { | ||||||
| 375 | return $settings{cgipath} if($settings{cgipath} =~ m!^http!); # we're assuming only http/https | ||||||
| 376 | return $settings{cgiroot}; | ||||||
| 377 | } | ||||||
| 378 | |||||||
| 379 | sub ScriptFile { | ||||||
| 380 | my %hash = @_; | ||||||
| 381 | my $path = ScriptPath() || ''; | ||||||
| 382 | my $file = $hash{file} || $settings{script}; | ||||||
| 383 | my $query = $hash{query} ? '?' . $hash{query} : ''; | ||||||
| 384 | |||||||
| 385 | return "$path/$file$query"; | ||||||
| 386 | } | ||||||
| 387 | |||||||
| 388 | =head2 Database Handling | ||||||
| 389 | |||||||
| 390 | =over 4 | ||||||
| 391 | |||||||
| 392 | =item DBConnect() | ||||||
| 393 | |||||||
| 394 | The method to initiate the Database access object. The method passes the | ||||||
| 395 | values held within the internal settings (set LoadSettings()), to the DB | ||||||
| 396 | access object constructor. It returns and stores internally the object | ||||||
| 397 | reference, which can be accessed across the system via the $dbi scalar. | ||||||
| 398 | |||||||
| 399 | =item dbh | ||||||
| 400 | |||||||
| 401 | Returns the reference to the DB access object, as created by the DBConnect() | ||||||
| 402 | method, or calls DBConnect() if not previously invoked. | ||||||
| 403 | |||||||
| 404 | =back | ||||||
| 405 | |||||||
| 406 | =cut | ||||||
| 407 | |||||||
| 408 | sub DBConnect { | ||||||
| 409 | return $dbi if $dbi; # object already exists | ||||||
| 410 | |||||||
| 411 | # use settings or defaults | ||||||
| 412 | my $logfile = $settings{logfile}; | ||||||
| 413 | my $phrasebook = $settings{phrasebook}; | ||||||
| 414 | my $dictionary = $settings{dictionary}; | ||||||
| 415 | |||||||
| 416 | $dbi = Labyrinth::DBUtils->new({ | ||||||
| 417 | driver => $settings{driver}, | ||||||
| 418 | database => $settings{database}, | ||||||
| 419 | dbfile => $settings{dbfile}, | ||||||
| 420 | dbhost => $settings{dbhost}, | ||||||
| 421 | dbport => $settings{dbport}, | ||||||
| 422 | dbuser => $settings{dbuser}, | ||||||
| 423 | dbpass => $settings{dbpass}, | ||||||
| 424 | autocommit => $settings{autocommit}, | ||||||
| 425 | logfile => $logfile, | ||||||
| 426 | phrasebook => $phrasebook, | ||||||
| 427 | dictionary => $dictionary, | ||||||
| 428 | }); | ||||||
| 429 | LogDebug("DBConnect DONE"); | ||||||
| 430 | |||||||
| 431 | $dbi; | ||||||
| 432 | } | ||||||
| 433 | |||||||
| 434 | # used by the DB access object | ||||||
| 435 | sub _errors { | ||||||
| 436 | my $err = shift; | ||||||
| 437 | my $sql = shift; | ||||||
| 438 | my $message = ''; | ||||||
| 439 | |||||||
| 440 | $message = "$err " if($err); |
||||||
| 441 | $message .= " SQL=$sql " if($sql); |
||||||
| 442 | $message .= "ARGS=[".join(",",@_)."]" if(@_); | ||||||
| 443 | |||||||
| 444 | $tvars{failures} = [ { code => 'DB', message => $message } ]; | ||||||
| 445 | PublishCode('MESSAGE'); | ||||||
| 446 | exit; | ||||||
| 447 | } | ||||||
| 448 | |||||||
| 449 | sub dbh { | ||||||
| 450 | $dbi || DBConnect; | ||||||
| 451 | } | ||||||
| 452 | |||||||
| 453 | =head2 Interface Parameter Handling | ||||||
| 454 | |||||||
| 455 | =over 4 | ||||||
| 456 | |||||||
| 457 | =item ParseParams($rules) | ||||||
| 458 | |||||||
| 459 | ParseParams() reads and validates the interface (CGI) parameters that are sent | ||||||
| 460 | via a HTTP request, before storing them in the %cgiparams hash. Each parameter | ||||||
| 461 | must have a rule for it to be accepted. | ||||||
| 462 | |||||||
| 463 | The rules file (default is parserules.ini) is automatically loaded and stored. | ||||||
| 464 | |||||||
| 465 | All valid input parameter values (scalars only) are also automatically stored | ||||||
| 466 | in the template variable hash, %tvars. This is to enable templates to be | ||||||
| 467 | reparsed in the event of an error, and retain the user's valid entries. | ||||||
| 468 | |||||||
| 469 | =back | ||||||
| 470 | |||||||
| 471 | =cut | ||||||
| 472 | |||||||
| 473 | sub ParseParams { | ||||||
| 474 | LoadRules($_[0]) unless($settings{rulesloaded}); | ||||||
| 475 | |||||||
| 476 | my $results; | ||||||
| 477 | |||||||
| 478 | # LogDebug("rules=".Dumper(\%rules)); | ||||||
| 479 | |||||||
| 480 | if(!defined $ENV{'SERVER_SOFTWARE'}) { # commandline testing | ||||||
| 481 | my $file = "$settings{'config'}/cgiparams.nfo"; | ||||||
| 482 | if(-r $file) { | ||||||
| 483 | my $fh = IO::File->new($file, 'r') or return; | ||||||
| 484 | my (%params,$params); | ||||||
| 485 | { local $/ = undef; $params = <$fh>; } | ||||||
| 486 | $fh->close; | ||||||
| 487 | foreach my $param (split(/[\r\n]+/,$params)) { | ||||||
| 488 | my ($name,$value) = $param =~ /(\w+)=(.*)/; | ||||||
| 489 | next unless($name); | ||||||
| 490 | |||||||
| 491 | if($value =~ /\[([^\]]+)\]/) { | ||||||
| 492 | @{$params{$name}} = split(",",$1); | ||||||
| 493 | } else { | ||||||
| 494 | $params{$name} = $value; | ||||||
| 495 | } | ||||||
| 496 | } | ||||||
| 497 | |||||||
| 498 | LogDebug("params=".Dumper(\%params)); | ||||||
| 499 | $results = Data::FormValidator->check(\%params, \%rules); | ||||||
| 500 | $settings{testing} = 1; | ||||||
| 501 | } | ||||||
| 502 | |||||||
| 503 | } else { | ||||||
| 504 | my %fdat = $cgi->Vars; | ||||||
| 505 | LogDebug("fdat=".Dumper(\%fdat)); | ||||||
| 506 | |||||||
| 507 | # Due to a problem with DFV, we handle images separately | ||||||
| 508 | for my $param ( grep { /^IMAGEUPLOAD/ } keys %fdat ) { | ||||||
| 509 | if( $cgi->param($param) ) { | ||||||
| 510 | CGIFile($param); | ||||||
| 511 | $settings{cgiimages}{$param} = 1; | ||||||
| 512 | } | ||||||
| 513 | $cgi->delete($param) | ||||||
| 514 | } | ||||||
| 515 | |||||||
| 516 | # my %fields = map {$_ => 1} @{$rules{required}}, @{$rules{optional}}; | ||||||
| 517 | # for (keys %fdat) { | ||||||
| 518 | # LogDebug("NO RULE: $_") | ||||||
| 519 | # unless( $fields{$_} || | ||||||
| 520 | # ($rules{required_regexp} && $_ =~ $rules{required_regexp}) || | ||||||
| 521 | # ($rules{optional_regexp} && $_ =~ $rules{optional_regexp}) | ||||||
| 522 | # ); | ||||||
| 523 | # } | ||||||
| 524 | |||||||
| 525 | $results = Data::FormValidator->check($cgi, \%rules); | ||||||
| 526 | } | ||||||
| 527 | |||||||
| 528 | if($results) { | ||||||
| 529 | # LogDebug("results=".Dumper($results)); | ||||||
| 530 | my $values = $results->valid; | ||||||
| 531 | %cgiparams = %$values; | ||||||
| 532 | $values = $results->msgs; | ||||||
| 533 | foreach my $key (keys %$values) { | ||||||
| 534 | $tvars{$key} = $values->{$key} if($key =~ /^err_/); | ||||||
| 535 | } | ||||||
| 536 | |||||||
| 537 | # LogDebug("GOT RULE: env=" . Dumper(\%ENV)); | ||||||
| 538 | # LogDebug("GOT RULE: rules=" . Dumper(\%rules)); | ||||||
| 539 | } else { | ||||||
| 540 | LogDebug("NO Data::FormValidator RESULTS!"); | ||||||
| 541 | my( $valids, $missings, $invalids, $unknowns ) = Data::FormValidator->validate($cgi, \%rules); | ||||||
| 542 | LogDebug("NO RULE: valids=" . Dumper($valids)); | ||||||
| 543 | LogDebug("NO RULE: invalids=" . Dumper($invalids)); | ||||||
| 544 | # LogDebug("NO RULE: missings=" . Dumper($missings)); | ||||||
| 545 | # LogDebug("NO RULE: unknowns=" . Dumper($unknowns)); | ||||||
| 546 | # LogDebug("NO RULE: env=" . Dumper(\%ENV)); | ||||||
| 547 | # LogDebug("NO RULE: rules=" . Dumper(\%rules)); | ||||||
| 548 | %cgiparams = %$valids; | ||||||
| 549 | $cgiparams{'err_'.$_} = 'Invalid' for(@$invalids); | ||||||
| 550 | } | ||||||
| 551 | |||||||
| 552 | $cgiparams{$_} = 1 for(keys %{$settings{cgiimages}}); | ||||||
| 553 | |||||||
| 554 | LogDebug("cgiparams=".Dumper(\%cgiparams)); | ||||||
| 555 | LogInfo("ParseParams DONE"); | ||||||
| 556 | } | ||||||
| 557 | |||||||
| 558 | |||||||
| 559 | 1; | ||||||
| 560 | |||||||
| 561 | __END__ |