use Path::Class;
use Encode qw( decode_utf8 encode_utf8 is_utf8 );
use POSIX qw( strftime );
+use File::Copy;
extends 'FrBr::Common::MooseX::App';
};
}
+#-----------------------------------------
+
+=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
}
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;
}
}
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;
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 ( <FILE> ) {
+ 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;