From 155374e2f1ba8ed480f047cfb9761a8b55e750c8 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Thu, 5 Aug 2010 16:21:57 +0000 Subject: [PATCH] Bis zum Aufruf vom postmap/postalias gekommen git-svn-id: http://svn.brehm-online.com/svn/my-stuff/postfix-maps/trunk@108 ec8d2aa5-1599-4edb-8739-2b3a1bc399aa --- lib/FrBr/Postfix/App.pm | 310 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 308 insertions(+), 2 deletions(-) diff --git a/lib/FrBr/Postfix/App.pm b/lib/FrBr/Postfix/App.pm index b74ef39..2db4368 100644 --- a/lib/FrBr/Postfix/App.pm +++ b/lib/FrBr/Postfix/App.pm @@ -24,6 +24,7 @@ use MooseX::Types::Path::Class; use Path::Class; use Encode qw( decode_utf8 encode_utf8 is_utf8 ); use POSIX qw( strftime ); +use File::Copy; extends 'FrBr::Common::MooseX::App'; @@ -188,6 +189,35 @@ sub _build_valid_maptypes { }; } +#----------------------------------------- + +=head2 postfix_binary + +HashRef mit den Postfix-Binaries + +=cut + +has 'postfix_binary' => ( + is => 'ro', + isa => 'HashRef', + traits => [ 'NoGetopt' ], + lazy => 1, + builder => '_build_postfix_binary', + documentation => 'HashRef mit allen wichtigen Postfix-Binaries.', +); + +#------ + +sub _build_postfix_binary { + return { + 'postalias' => '/usr/sbin/postalias', + 'postconf' => '/usr/sbin/postconf', + 'postfix' => '/usr/sbin/postfix', + 'postmap' => '/usr/sbin/postmap', + }; +} + + #--------------------------------------------------------------------------- # Ändern der Eigenschaften einiger geerbter Attribute @@ -310,7 +340,7 @@ after 'evaluate_config' => sub { } if ( $self->verbose >= 2 ) { - for my $key qw( postfix_dir work_dir postfix_maps restart_postfix valid_maptypes ) { + for my $key qw( postfix_dir work_dir postfix_binary postfix_maps restart_postfix valid_maptypes ) { my $tmp = $self->$key; } } @@ -635,7 +665,7 @@ sub do_mapping { eval { for my $rs ( $self->schema->resultset($resultset)->search( $map->{'where'}, $o_opts )->all() ) { - my $field1 = $rs->get_column( $cols->[0] ); + my $field1 = encode_utf8( lc( decode_utf8( $rs->get_column( $cols->[0] ) ) ) ); my $field2 = $two_identic_cols ? $field1 : $rs->get_column( $cols->[1] ); $field1 .= ':' if $map->{'text_type'} eq 'aliases'; printf FILE "%-*s %s\n", $max_col_length, $field1, $field2; @@ -653,10 +683,286 @@ sub do_mapping { close FILE; + my $changed = 0; + my $binary = $self->postfix_binary; + + $changed = 1 unless -f $map->{'mapfile'}; + $changed = 1 if $self->_diff_files( $map->{'workfile'}, $map->{'mapfile'}, $map->{'text_type'} ); + $self->debug( sprintf( "Mapping '%s' hat sich %s.", $mapname, ( $changed ? 'GEÄNDERT' : 'NICHT VERÄNDERT' ) ) ); + + if ( $changed ) { + + $self->info( sprintf( "Aktualisiere Mapping '%s' in Datei '%s' ...", $mapname, $map->{'mapfile'} ) ); + + $self->debug( sprintf( "Kopiere Datei '%s' nach '%s' ...", $map->{'workfile'}, $map->{'mapfile'} ) ); + copy $map->{'workfile'}, $map->{'mapfile'}; + + if ( $map->{'exec_map'} ) { + + my $cmd = $map->{'text_type'} eq 'aliases' ? $binary->{'postalias'} : $binary->{'postmap'}; + my @Args = ( $cmd, $map->{'db_type'} . ":" . $map->{'mapfile'} ); + $self->debug( sprintf( "Führe Kommando aus: '%s'", join( " ", @Args ) ) ); + unless ( system(@Args) == 0 ) { + $self->error( sprintf( "Fehler beim Ausführen von '%s'.", join( " ", @Args ) ) ); + return undef; + } + } + + $self->restart_postfix(1) if $map->{'restart_postfix'}; + + } + return 1; } +#-------------------------------------------------------------------------------------- + +=head2 _diff_files( $file1, $file2, $map_type ) + +=cut + +sub _diff_files { + + my $self = shift; + my $file1 = shift; + my $file2 = shift; + my $map_type = shift; + + unless ( $file1 and $file2 ) { + $self->error("Keine Dateinamen zum Überprüfen übergeben."); + exit 9; + } + $self->debug( sprintf( "Vergleiche Inhalte der Dateien '%s' und '%s' ...", $file1, $file2 ) ) if $self->verbose >= 2; + return 1 unless -f $file1; + return 1 unless -f $file2; + + my $content1 = $self->_read_map_file( $file1, $map_type ); + my $content2 = $self->_read_map_file( $file2, $map_type ); + + return 1 unless $content1 and ref($content1) and ref($content1) eq 'ARRAY'; + return 1 unless $content2 and ref($content2) and ref($content2) eq 'ARRAY'; + + return 1 unless scalar(@$content1) == scalar(@$content2); + my $length = scalar(@$content1); + + my $i = 0; + my $they_are_different = 0; + + for ( $i = 0; $i < $length; $i++ ) { + + my $row1 = $content1->[$i]; + my $row2 = $content2->[$i]; + + unless ( $row1 and ref($row1) and ref($row1) eq 'ARRAY' ) { + $they_are_different = 1; + last; + } + + unless ( $row2 and ref($row2) and ref($row2) eq 'ARRAY' ) { + $they_are_different = 1; + last; + } + + unless ( scalar(@$row1) == scalar(@$row2) ) { + $they_are_different = 1; + last; + } + + if ( defined( $row1->[0] ) ) { + unless ( defined( $row2->[0] ) ) { + $they_are_different = 1; + last; + } + } + elsif ( defined( $row2->[0] ) ) { + $they_are_different = 1; + last; + } + else { + next; + } + + unless ( $row1->[0] eq $row2->[0] ) { + $they_are_different = 1; + last; + } + + my $values1 = $row1->[1]; + my $values2 = $row2->[1]; + + if ( defined($values1) ) { + unless ( defined($values2) ) { + $they_are_different = 1; + last; + } + } + elsif ( defined($values2) ) { + $they_are_different = 1; + last; + } + else { + next; + } + + unless ( $values1 and ref($values1) and ref($values1) eq 'ARRAY' ) { + $they_are_different = 1; + last; + } + + unless ( $values2 and ref($values2) and ref($values2) eq 'ARRAY' ) { + $they_are_different = 1; + last; + } + + unless ( scalar(@$values1) == scalar(@$values2) ) { + $they_are_different = 1; + last; + } + next unless scalar(@$values1); + + my $vals_diff = 0; + VALUES: for ( my $j = 0; $j < scalar(@$values1); $j++ ) { + + my $v1 = $values1->[$j]; + my $v2 = $values2->[$j]; + + if ( defined($v1) ) { + unless ( defined($v2) ) { + $vals_diff = 1; + last VALUES; + } + } + elsif ( defined($v2) ) { + $vals_diff = 1; + last VALUES; + } + else { + next VALUES; + } + + if ( $v1 ne $v2 ) { + $vals_diff = 1; + last VALUES; + } + + } + + if ( $vals_diff ) { + $they_are_different = 1; + last; + } + + } + + return $they_are_different; + +} + +#--------------------------------- + +=head2 _read_map_file( $file, $type ) + +Liest eine Postfix-Mapdatei aus und liefert eine Datenstruktur zurück + +=cut + +sub _read_map_file { + + my $self = shift; + my $file = shift; + my $type = shift; + + $type ||= 'map'; + + unless ( $file ) { + $self->error( "Kein Dateiname zum Einlesen übergeben." ); + return undef; + } + + unless ( -f $file ) { + $self->warn( sprintf( "Datei '%s' existiert nicht.", $file ) ); + return undef; + } + + my $content = []; + my $line = ''; + + $self->debug( sprintf( "Lese Datei '%s' ein ...", $file ) ) if $self->verbose >= 3; + unless ( open FILE, "<", $file ) { + $self->error( sprintf( "Konnte Datei '%s' nicht zum Lesen öffnen: %s", $file, $! ) ); + return undef; + } + + while ( ) { + next if /^\s*#/; + if ( /^\s*$/ ) { + push @$content, $self->_parse_line( $line, $type ) if $line; + $line = ''; + next; + } + if ( /^\s/ ) { + if ( $line ) { + s/\s+$//; + $line .= $_; + next; + } + push @$content, $self->_parse_line( $_, $type ); + next; + } + push @$content, $self->_parse_line( $line, $type ) if $line; + $line = $_; + } + push @$content, $self->_parse_line( $line, $type ) if $line; + + close FILE; + + $self->debug( "Gelesener Dateiinhalt: ", $content ) if $self->verbose >= 4; + return $content; + +} + +#-------------------------------------------------------------------------------------- + +=head2 _parse_line( $line, $map_type ) + +=cut + +sub _parse_line { + + my $self = shift; + my $line = shift; + my $map_type = shift; + return [] unless $line; + + $self->debug( sprintf( "Parse Zeile '%s' ...", $line ) ) if $self->verbose >= 4; + $line =~ s/^\s+//; + $line =~ s/\s+$//; + + my $res = []; + + return [] if $line =~ /^\s*$/; + + my ( $key, $rest ); + my $match = $map_type eq 'aliases' ? '^(\\S+)\\s*:\\s*(\\S.*)' : '^(\\S+)\\s+(\\S.*)'; + $self->debug( sprintf( "Match-RegEx: '%s'.", $match ) ) if $self->verbose >= 4; + + unless ( ( $key, $rest ) = $line =~ /$match/ismx ) { + return []; + } + + push @$res, $key; + + my $targets = []; + @$targets = split /\s*,\s*/, $rest; + push @$res, ( scalar( @$targets ) ? $targets : $rest ); + + $self->debug( "Geparste Zeile: ", $res ) if $self->verbose >= 4; + return $res; + +} + + #--------------------------------- __PACKAGE__->meta->make_immutable; -- 2.39.5