#!/usr/local/bin/perl -w # @(#) SEPserverPGP.pl Получает Secure-EMail-Print файлы с POP3-сервера и # передаёт их на указанный(ые) принтер(ы). Требуется 'pgp'. # Прдназначен для вызова через inittab # Graham Jenkins, IBM GSA, Декабрь. 2001. Пересмотрено: 4 января. 2002. use strict; use File::Basename; use Net::POP3; use Date::Manip; use IO::File; use Sys::Syslog qw(:DEFAULT setlogsock); my $host="bronzeback.in.telstra.com.au"; # Один и тот же хост и пароль для my $pass="4no12c"; # каждого принтера. my ($printer); defined($ARGV[0]) || die "Usage: ", basename($0). " printer1 [ printer2 ..]\n"; my $tmp = "/tmp/".basename($0)."_". $ARGV[0]; setlogsock('unix'); openlog(basename($0), 'cons,nowait', 'local7'); syslog ('info',"Starting .."); while (1) { # Вечный цикл, обработка sleep 30; # всех принтеров в каждом цикле, и foreach $printer (@ARGV) {process($printer);} # пауза в 30 секунд } # между двумя циклами. sub process { my ($flag,$i,$j,$k,$l,$m,$user,$pop,@field,@part,$count,$top15, $msgdate,$parsdate,%slot,$fh,%tp,$message,$buffer,$print); $user = $_[0]; $pop = Net::POP3->new($host); # Входим на POP3-сервер и получаем $count = $pop->login($user,$pass) ; # заголовок плюс первые 15 строк $count = -1 if ! defined ($count) ; # каждого сообщения. Используем apop, for ($i = 1; $i <= $count; $i++ ) { # если он поддерживается сервером. $top15=$pop->top($i,15) ; if ($top15) { undef @part; $msgdate = ""; for ($j = 0; $j < 99; $j++ ) { if (@$top15[$j]) { # Используем дату прибытия на POP3-сервере if($msgdate eq "") { # для определения возраста письма; (@field) = split(/;/,@$top15[$j]); # если письмо устарело - if ( defined($field[1])) { # удаляем его и переходим к следующему. $parsdate=&ParseDate($field[1]); # (Ищем точку с запятой, после которой if( $parsdate ) { # идет корректная дата.) $msgdate="Y"; if(&Date_Cmp($parsdate, &DateCalc("today","-3 days") ) lt 0 ) { syslog('info',"Stale msg: $user $parsdate"); $pop->delete($i); goto I # Если POP3-сервер автоматически } # фильтрует письма на предмет устаревания, } # то эту часть можно полностью } # опустить. } (@field)=split(/ /,@$top15[$j]);$m=0; # Извлекаем content-type поля. while (defined($field[$m])) { if ( $field[$m] =~ m/^-----BEGIN/){ # Начало PGP-сообщения if(! defined $part[1]) {foreach $m (0,1,2){$part[$m]=1}} } elsif( $field[$m] =~ m/^id=/ ) { # id -- уникальный номер сообщения $part[0]=$field[$m]; $part[0]=~s/id=//; $part[0]=~s/\;// } elsif( $field[$m] =~ m/^number=/ ){ # number -- порядковый номер части сообщения $part[1]=$field[$m]; $part[1]=~s/\D//g } elsif( $field[$m] =~ m/^total=/ ) { # total -- общее кол-во частей $part[2]=$field[$m]; $part[2]=~s/\D//g } $m++ } if (defined($part[0]) && defined($part[1])) { $slot{$part[0]."=".$part[1]}=$i; # Если обнаружены поля id и number, то записываем if ( defined($part[2]) ) { # порядковый номер сообщения в почтовом ящике в массив $slot. $tp{$part[0]} = $part[2] if $part[2] eq $part[1] } } goto J if ! defined($part[0]) ; goto I if ! defined($tp{$part[0]}); for ($k=1;$k<=$tp{$part[0]};$k++){ # Проверяем все ли части сообщения собраны. goto I if ! defined($slot{$part[0]."=".$k}); } $fh=new IO::File "| /usr/local/bin/pgp -f 2>$tmp |lpr -P $user >/dev/null" or goto I; for ($k=1;$k<=$tp{$part[0]};$k++){ # Компонуем части сообщения и передаём в конвейер. $message=$pop->get($slot{$part[0]."=".$k}); $l=0; $buffer=""; $print="N"; while ( defined(@$message[$l]) ) { chomp @$message[$l]; # Часть 1: начинается со строки "-----BEGIN", if( $k == 1 ) { # стоп перед 2-й пустой строкой. if( @$message[$l]=~m/^-----BEGIN/ ) { $m=-2; $print="Y"} if( $print eq "Y" ) { if( @$message[$l] eq "" ) { $m++; if( $m >= 0) {last} } $buffer=$buffer.@$message[$l]."\n" } } # Части 2,3,..: пропустить 1 пустую строку else { # после "id=", старт; стоп if( $print eq "Y" ) { # перед следующей пустой строкой. if( @$message[$l] eq "" ) {last} $buffer=$buffer.@$message[$l]."\n" } if( @$message[$l]=~m/id=/ ) {$print="R"} if((@$message[$l] eq "") && ($print eq "R")) {$print="Y"} } $l++; } print $fh $buffer or goto I; } $fh->close || goto I; open $fh, $tmp; while (<$fh>) { chomp; syslog('info', $_) } close $fh; for ($k=1;$k<=$tp{$part[0]};$k++){ $pop->delete($slot{$part[0]."=".$k}) } goto I; } J: } } I:} $pop->quit() if ($count >= 0); }