diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in index 54cc8c3f3..754e4a591 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -31,6 +31,7 @@ use warnings; require Exporter; require ZoneMinder::Base; require ZoneMinder::Database; +use ZoneMinder::ConfigData qw(:all); our @ISA = qw(Exporter ZoneMinder::Base); @@ -45,7 +46,12 @@ use vars qw( %Config ); our @EXPORT_CONFIG = qw( %Config ); # Get populated by BEGIN our %EXPORT_TAGS = ( - 'constants' => [ qw( + functions => [ qw( + zmConfigLoad + loadConfigFromDB + saveConfigToDB + ) ], + constants => [ qw( ZM_PID ) ] ); @@ -67,47 +73,163 @@ use Carp; sub zmConfigLoad { %Config = (); - my $config_file = ZM_CONFIG; - open( my $CONFIG, "<", $config_file ) - or croak( "Can't open config file '$config_file': $!" ); - foreach my $str ( <$CONFIG> ) - { - next if ( $str =~ /^\s*$/ ); - next if ( $str =~ /^\s*#/ ); - my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/; - if ( ! $name ) { - print( STDERR "Warning, bad line in $config_file: $str\n" ); - next; - } # end if - $name =~ tr/a-z/A-Z/; - $Config{$name} = $value; - } - close( $CONFIG ); + my $config_file = ZM_CONFIG; + open( my $CONFIG, "<", $config_file ) + or croak( "Can't open config file '$config_file': $!" ); + foreach my $str ( <$CONFIG> ) { + next if ( $str =~ /^\s*$/ ); + next if ( $str =~ /^\s*#/ ); + my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.*?)\s*$/; + if ( ! $name ) { + print( STDERR "Warning, bad line in $config_file: $str\n" ); + next; + } # end if + $name =~ tr/a-z/A-Z/; + $Config{$name} = $value; + } + close( $CONFIG ); - my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); - my $sql = 'select * from Config'; - my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); - while( my $config = $sth->fetchrow_hashref() ) { - $Config{$config->{Name}} = $config->{Value}; + my $dbh = ZoneMinder::Database::zmDbConnect() or croak( "Can't connect to db" ); + my $sql = 'select * from Config'; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + while( my $config = $sth->fetchrow_hashref() ) { + $Config{$config->{Name}} = $config->{Value}; + } + $sth->finish(); + + if ( ! exists $Config{ZM_SERVER_ID} ) { + $Config{ZM_SERVER_ID} = undef; + $sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' ); + if ( $Config{ZM_SERVER_NAME} ) { + $res = $sth->execute( $Config{ZM_SERVER_NAME} ); + my $result = $sth->fetchrow_hashref(); + $Config{ZM_SERVER_ID} = $$result{Id}; + } elsif ( $Config{ZM_SERVER_HOST} ) { + $res = $sth->execute( $Config{ZM_SERVER_HOST} ); + my $result = $sth->fetchrow_hashref(); + $Config{ZM_SERVER_ID} = $$result{Id}; } $sth->finish(); - - if ( ! exists $Config{ZM_SERVER_ID} ) { - $Config{ZM_SERVER_ID} = undef; - $sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' ); - if ( $Config{ZM_SERVER_NAME} ) { - $res = $sth->execute( $Config{ZM_SERVER_NAME} ); - my $result = $sth->fetchrow_hashref(); - $Config{ZM_SERVER_ID} = $$result{Id}; - } elsif ( $Config{ZM_SERVER_HOST} ) { - $res = $sth->execute( $Config{ZM_SERVER_HOST} ); - my $result = $sth->fetchrow_hashref(); - $Config{ZM_SERVER_ID} = $$result{Id}; - } - } + } } +sub loadConfigFromDB { + print( "Loading config from DB\n" ); + my $dbh = ZoneMinder::Database::zmDbConnect(); + if ( !$dbh ) { + print( "Error: unable to load options from database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) + or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() + or croak( "Can't execute: ".$sth->errstr() ); + my $option_count = 0; + while( my $config = $sth->fetchrow_hashref() ) { + my ( $name, $value ) = ( $config->{Name}, $config->{Value} ); +#print( "Name = '$name'\n" ); + my $option = $options_hash{$name}; + if ( !$option ) { + warn( "No option '$name' found, removing" ); + next; + } +#next if ( $option->{category} eq 'hidden' ); + if ( defined($value) ) { + if ( $option->{type} == $types{boolean} ) { + $option->{value} = $value?"yes":"no"; + } else { + $option->{value} = $value; + } + } + $option_count++;; + } + $sth->finish(); + return( $option_count ); +} + +sub saveConfigToDB { + print( "Saving config to DB\n" ); + my $dbh = ZoneMinder::Database::zmDbConnect(); + if ( !$dbh ) + { + print( "Error: unable to save options to database: $DBI::errstr\n" ); + return( 0 ); + } + + my $ac = $dbh->{AutoCommit}; + $dbh->{AutoCommit} = 0; + + $dbh->do('LOCK TABLE Config WRITE') + or croak( "Can't lock Config table: " . $dbh->errstr() ); + + my $sql = "delete from Config"; + my $res = $dbh->do( $sql ) + or croak( "Can't do '$sql': ".$dbh->errstr() ); + + $sql = "replace into Config set Id = ?, Name = ?, Value = ?, Type = ?, DefaultValue = ?, Hint = ?, Pattern = ?, Format = ?, Prompt = ?, Help = ?, Category = ?, Readonly = ?, Requires = ?"; + my $sth = $dbh->prepare_cached( $sql ) + or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $option ( @options ) + { +#next if ( $option->{category} eq 'hidden' ); +#print( $option->{name}."\n" ) if ( !$option->{category} ); + $option->{db_type} = $option->{type}->{db_type}; + $option->{db_hint} = $option->{type}->{hint}; + $option->{db_pattern} = $option->{type}->{pattern}; + $option->{db_format} = $option->{type}->{format}; + if ( $option->{db_type} eq "boolean" ) + { + $option->{db_value} = ($option->{value} eq "yes") + ? "1" + : "0" + ; + } + else + { + $option->{db_value} = $option->{value}; + } + if ( my $requires = $option->{requires} ) + { + $option->{db_requires} = join( ";", + map { + my $value = $_->{value}; + $value = ($value eq "yes") + ? 1 + : 0 + if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ) + ; ( "$_->{name}=$value" ) + } @$requires + ); + } + else + { + } + my $res = $sth->execute( + $option->{id}, + $option->{name}, + $option->{db_value}, + $option->{db_type}, + $option->{default}, + $option->{db_hint}, + $option->{db_pattern}, + $option->{db_format}, + $option->{description}, + $option->{help}, + $option->{category}, + $option->{readonly} ? 1 : 0, + $option->{db_requires} + ) or croak( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + + $dbh->do('UNLOCK TABLES'); + $dbh->{AutoCommit} = $ac; +} + +1; +__END__ 1; __END__ @@ -117,7 +239,7 @@ ZoneMinder::Config - ZoneMinder configuration module. =head1 SYNOPSIS - use ZoneMinder::Config qw(:all); +use ZoneMinder::Config qw(:all); =head1 DESCRIPTION @@ -132,7 +254,25 @@ namespace of the calling program or module. Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. - $lang = $Config{ZM_LANG_DEFAULT}; +$lang = $Config{ZM_LANG_DEFAULT}; + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with +the definitions held in this module. This results in the merging of any new +configuration and the removal of any deprecated configuration while +preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and +saving configuration is a convenient way to ensure that the configuration +held in the database corresponds with the most recent definitions and that +all components are using the same set of configuration. =head2 EXPORT @@ -155,7 +295,7 @@ Copyright (C) 2001-2008 Philip Coombes This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, -at your option, any later version of Perl 5 you may have available. + at your option, any later version of Perl 5 you may have available. -=cut + =cut