# UVconfig: Reads config files and tests configuration # Used by all components package UVconfig; use strict; use Net::Domain qw(hostname hostfqdn hostdomain); use UVmessage; use vars qw(@ISA @EXPORT $VERSION $usevote_version %config %messages @rules @groups $bdsg_regexp $bdsg2_regexp %ids %functions); require Exporter; @ISA = qw(Exporter); @EXPORT = qw($usevote_version %config %messages @rules @groups $bdsg_regexp $bdsg2_regexp %ids %functions); # Module version $VERSION = "0.18"; # Usevote version $usevote_version = "UseVoteGer 4.09"; sub read_config { my ($cfgfile, $redir_errors) = @_; # Default configuration options (overwritten in usevote.cfg) %config = (votefile => "votes", votename => "unkonfiguriertes Usevote", resultfile => "ergebnis.alle", rulefile => "usevote.rul", badaddrfile => "mailpatterns.cfg", messagefile => "messages.cfg", idfile => "scheinkennungen", requestfile => "anforderung", errorfile => "errors.log", lockfile => "usevote.lock", replyto => 0, personal => 0, proportional => 0, bdsg => 0, onestep => 0, multigroup => 0, voteack => 1, voteaccount => "<> (unkonfiguriertes Usevote)", mailfrom => "<> (unkonfiguriertes Usevote)", envelopefrom => "<>", mailstart => "^From ", archivedir => "fertig", tmpdir => "tmp", templatedir => "templates", formats => "UVformats.pm", domailfile => "tmp/domail", controlfile => "tmp/ack.control", mailcmd => "sendmail -oi -oem", mailcc => "", sleepcmd => "sleep 1", clearcmd => "clear", pager => "less", pop3 => 0, pop3server => "localhost", pop3port => 110, pop3user => "default", pop3pass => "default", pop3delete => 0, pop3uidlcache => "uidlcache", pop3server_req => "localhost", pop3port_req => 110, pop3user_req => "default", pop3pass_req => "default", pop3delete_req => 0, pop3uidlcache_req => "uidlcache_req", pop3server_bounce => "localhost", pop3port_bounce => 110, pop3user_bounce => "default", pop3pass_bounce => "default", pop3delete_bounce => 0, pop3uidlcache_bounce => 'uidlcache_bounce', smtp => 0, smtpserver => 'localhost', smtpport => 25, smtphelo => hostfqdn(), fqdn => hostfqdn(), smtpauth => 0, smtpuser => '', smtppass => '', name_re => '[a-zA-ZäöüÄÖÜß-]{2,} +.*[a-zA-ZäöüÄÖÜß]{2,}', ja_stimme => '(J\s*A|J|(D\s*A\s*)?F\s*U\s*E\s*R)', nein_stimme => '(N\s*E\s*I\s*N|N|(D\s*A\s*)?G\s*E\s*G\s*E\s*N)', enth_stimme => '(E|E\s*N\s*T\s*H\s*A\s*L\s*T\s*U\s*N\s*G)', ann_stimme => 'A\s*N\s*N\s*U\s*L\s*L\s*I\s*E\s*R\s*U\s*N\s*G', condition1 => '$yes>=2*$no', # twice as many yes as no condition2 => '$yes>=60', # min 60 yes votes prop_formula => '$yes/$no', tpl_ack_mail => 'ack-mail', tpl_bouncelist => 'bouncelist', tpl_mailheader => 'mailheader', tpl_result_multi => 'result-multi', tpl_result_single => 'result-single', tpl_result_prop => 'result-proportional', tpl_votes_multi => 'votes-multi', tpl_votes_single => 'votes-single', tpl_voterlist => 'voterlist', tpl_ballot => 'ballot', tpl_ballot_request => 'ballot-request', tpl_ballot_personal => 'ballot-personal', tpl_addr_reg => 'address-not-registered', tpl_no_ballotid => 'no-ballotid', tpl_wrong_ballotid => 'wrong-ballotid', tpl_bdsg_error => 'bdsg-error', tpl_cancelled => 'cancelled', tpl_invalid_account => 'invalid-account', tpl_invalid_name => 'invalid-name', tpl_multiple_votes => 'multiple-votes', tpl_no_ballot => 'no-ballot', tpl_no_votes => 'no-votes', tpl_rule_violated => 'rule-violated', begin_divider => 'Alles vor dieser Zeile bitte loeschen', end_divider => 'Alles nach dieser Zeile bitte loeschen', nametext => 'Dein Realname, falls nicht im FROM-Header:', nametext2 => 'Waehlername:', addresstext => 'Waehleradresse:', ballotidtext => 'Wahlscheinkennung:', bdsgtext => 'Datenschutzklausel - Zustimmung', bdsgfile => 'bdsgtext.cfg', rightmargin => 72, usevote_version => $usevote_version); # needed for use in templates # read config read_file($cfgfile); # read message file open (RES, "<$config{messagefile}") or die "Could not read message file $config{messagefile}!\n\n"; my @lines = ; close(RES); foreach my $line (@lines) { chomp($line); $line =~ s/^#.*//; # Delete comments if ($line =~ m/^\s*([A-Za-z0-9_-]+)\s*=\s*(.+)\s*$/){ $messages{$1} = $2; } } # missing "groupX =" lines in config file? die UVmessage::get("CONF_NOGROUPS", CONFIGFILE=>$cfgfile) . "\n\n" unless (@groups); # redirect errors to a file if desired by calling script open (STDERR, ">$config{errorfile}") if ($redir_errors); # check for data protection law? read text for ballot parse_bdsgtext() if ($config{bdsg}); # personalized ballots? read ballot IDs read_ballot_ids() if ($config{personal}); load_formats() if ($config{formats}); } ############################################################################## # read config file # ############################################################################## sub read_file { my $cfgfile = shift; my $CONFIG; open ($CONFIG, "<$cfgfile") or die "Could not find config file $cfgfile!\n\n"; while (<$CONFIG>) { next if (/^#/); # line is a comment chomp; # delete \n s/\r//; # delete \r if present s/([^\\])#.*$/$1/; # Remove comments not starting at beginning of line. # (ignore escaped comment sign \#) if (/^include (\S+)$/) { # include other config file read_file($1); } elsif (my($key, $value) = split (/\s*=\s*/, $_, 2)) { # delete trailing spaces $value =~ s/\s*$//; # evaluate quotation marks $value =~ s/^\"([^\"]+[^\\\"])\".*$/$1/; $value =~ s/\\"/"/g; if ($key =~ /^group(\d+)$/) { my $num = $1; $groups[$num-1] = $value; # internal index starts at 0 } else { $config{$key} = $value; } } } close ($CONFIG); } ############################################################################## # parse data protection law texts # ############################################################################## sub parse_bdsgtext { open (BDSG, "<$config{bdsgfile}") or die UVmessage::get("CONF_NOBDSGFILE", ('BDSGFILE' => "$config{bdsgfile}")) . "\n\n"; my @bdsg = ; close BDSG; $config{bdsginfo} = ''; foreach my $line (@bdsg) { $config{bdsginfo} .= $line unless ($line =~ /^\s*#/); } my $bdsgtmp = $config{bdsginfo}; $bdsgtmp =~ s/\"/\\\"/g; $bdsgtmp =~ s/\'/\\\'/g; $bdsgtmp =~ s/\(/\\\(/g; $bdsgtmp =~ s/\)/\\\)/g; $bdsgtmp =~ s/\[/\\\[/g; $bdsgtmp =~ s/\]/\\\]/g; $bdsgtmp =~ s/\./\\\./g; $bdsgtmp =~ s/\!/\\\!/g; my @bdsgtext = split(' ', $bdsgtmp); # Build Regular Expression from single words. # There has to be at least a space between two words, additional characters # are allowed, e.g. quotation marks (but no letters) $bdsg_regexp = join('\s\W*?', @bdsgtext); # Build Regular Expression from $config{bdsgtext} $bdsg2_regexp = join('\s\W*?', split(' ', $config{bdsgtext})); } ############################################################################## # Read suspicious mail addresses (normally mailpatterns.cfg) # ############################################################################## sub read_badaddr { my @bad_addr = (); open (BADADDR, "<$config{badaddrfile}") or die UVmessage::get("CONF_NOBADADDR",(BADADDRFILE => $config{badaddrfile})) . "\n\n"; while () { chomp; # Comment line? Not only whitespaces? if (/^[^#]/ && /[^\s]/) { push(@bad_addr, $_); } } close (BADADDR); return @bad_addr; } ############################################################################## # Read ballot IDs # ############################################################################## sub read_ballot_ids { # open file with ballot ids open(FILE, "<$config{idfile}") or return 1; while () { chomp; # Format: mailaddress (whitespace) ballot ID if (/^(.+@.+)\s+([a-z0-9]+)/) { # $1=mailadresse, $2=ballot ID $ids{$1} = $2; } } close(FILE); return 0; } ############################################################################## # Funktionen für Templates laden # ############################################################################## sub load_formats { my $modules = $config{formats}; my @modules = split(/\s*,\s*/, $modules); foreach my $module (@modules){ if (-r $module){ require $module; } } } ############################################################################## # config test # ############################################################################## sub test_config { print UVmessage::get("CONF_CONFIG"), "\n\n"; foreach my $option (keys %config) { print "$option = $config{$option}\n"; } print "\n", UVmessage::get("CONF_TEST_RULES"); if (@rules) { print "\n\n"; for (my $n=0; $n<@rules; $n++) { my $text = UVrules::rule_print($n); print $text; } print "\n"; } else { print UVmessage::get("CONF_NO_RULES"), "\n\n"; } } 1;