X-Git-Url: https://git.deb.at/?p=pkg%2Ft-prot.git;a=blobdiff_plain;f=t-prot;h=1d51b3bb356d5b730b1f4e0fc17e2aa76557df12;hp=bb2a0c239de4cfe3b298f7df91e392d25bde5aab;hb=c76d75ee035107bbb03e21561b4c206e4efe7743;hpb=c8ccc73dba899e9fdf86195394ce069b8daf1e15;ds=sidebyside diff --git a/t-prot b/t-prot index bb2a0c2..1d51b3b 100755 --- a/t-prot +++ b/t-prot @@ -1,13 +1,13 @@ #!/usr/bin/perl -w -# $Id: t-prot,v 1.285 2010/02/15 20:13:00 jochen Exp $ +# $Id: t-prot,v 1.298 2010/03/06 01:32:50 jochen Exp $ require 5.006; use strict; use Fcntl qw(O_EXCL O_WRONLY O_CREAT); -use Getopt::Mixed qw(nextOption); -use constant VER => '2.15'; +use Getopt::Long qw(:config gnu_getopt no_ignore_case); +use constant VER => '2.97'; use constant REV => ''; -use constant REL => q$Revision: 1.285 $=~m/(\d+(?:\.\d+)+)/; +use constant REL => q$Revision: 1.298 $=~m/(\d+(?:\.\d+)+)/; # MTA expecting mail on STDIN # (you might have to adjust this if using a different MTA) use constant SENDMAIL => '/usr/sbin/sendmail -oi'; @@ -21,7 +21,7 @@ use constant EX_SOFTWARE => 70; use constant EX_IOERR => 74; use constant EX_BOUNCE => EX_UNAVAILABLE; use vars qw( - $ad $ads $bigqn $bigqx $boun $check $check_ratio $cr $diff $elli + $ad $ads $bigqn $bigqx $boun $check $check_ratio $cr $crshrink $diff $elli $footers $ftr_ad $ftr_ml $hdrs $indent $kamm $kdiff $kminl $kmaxl $lax $lsig $maxsig $maxlines $mda $ml $gw $ms $ms_smart $msg_quote $msg_ratio $mua $nohdr $ofile $pgpshort $pgpmove $pgpmovevrf $reply @@ -42,6 +42,7 @@ use vars qw( $0 =~ s!^.*/!!; $maxsig = 4; # max. valid signature length $maxlines = undef; # no limit of message lines +$crshrink = 2; # multiple blank lines are shrunk to $crshrink lines $indent = '>'; # Indent string, regexp to identify a quoted line $kminl = 65; # see decomb() for details $kmaxl = 80; @@ -88,28 +89,28 @@ $gpg_bug = '... this is a bug ('; # help(): print help text and exit with appropriate exit code sub help { print "Usage: $0 [options] - -A=DIRECTORY ad footer directory, treat ad footers as signature + -A DIRECTORY ad footer directory, treat ad footers as signature -a remove ad footers; requires -A --bigq[=n[,x]] remove all but x lines of quotes with more than n lines; default is n=30 and x=10 --body input has no headers; does not work with --pgp-short; multipart messages will not be detected - -c merge multiple blank lines + -c[n] merge multiple blank lines to n lines (default is 2) --check[=FLAGS] check various criteria, print error message and quit; see man page for details -d, --debug print notice to syslog when bouncing; requires -p - --diff tolerate diffs appended *after* the signature + --diff tolerate diffs -e force ellipsis for excessive punctuation --ftr-ad enable aggressive ad footer matching; requires -A --ftr-ml enable aggressive mailing list footer matching; req. -L --groupwise delete Novell Groupwise style TOFU -h, --help show this short help and exit - -i=INFILE file to be read; '-' for STDIN (default) + -i INFILE file to be read; '-' for STDIN (default) -k try to fix \"Kammquotes\" - --kminl=n min. line length for wrapped line; requires -k - --kmaxl=n max. line length for wrapped line; requires -k --kdiff=n max. length difference between wrapped lines; req. -k - -L=DIRECTORY mailing list footer directory, treat mailing list + --kmaxl=n max. line length for wrapped line; requires -k + --kminl=n min. line length for wrapped line; requires -k + -L DIRECTORY mailing list footer directory, treat mailing list footers as signature -l delete mailing list footer; requires -L --lax-security use unsafe writing method; USE ON YOUR OWN RISK! @@ -118,16 +119,15 @@ sub help { -m delete MS style TOFU; careful: might be too agressive --max-lines=x maximum number of message lines --ms-smart try to be smart with MS style TOFU; req. -Mmutt and -m - -o=OUTFILE file to be written to; '-' for STDOUT (default), 'NONE' - for no output at all - -P=MESSAGE user defined bounce message; requires -p - -p[=ADDRESS] redirect to ADDRESS if no TOFU was found + -o OUTFILE file to be written to; '-' for STDOUT (default) + -P MESSAGE user defined bounce message; requires -p + -p[ADDRESS] redirect to ADDRESS if no TOFU was found --pgp-move move pgp verification output to bottom; requires -Mmutt --pgp-move-vrf move pgp output if verified and good; requires -Mmutt --pgp-short hide non-relevant pgp key uids; requires -Mmutt -r delete mail header lines --reply squeeze multiple reply prefixes in subject line - -S[=n] supress signatures with more than n lines (default $maxsig) + -S[n] supress signatures with more than n lines (default $maxsig) -s delete signature --sani sanitize some header fields --sigsmax[=n] max number of sigs tolerated, no value for unlimited @@ -359,7 +359,7 @@ sub debigq { my $x = $k-$bigqx; $i -= $k; - $$L[$i] = "[---=| Quote block shrinked by $0: " . + $$L[$i] = "[---=| Quote block shrunk by $0: " . "$x lines snipped |=---]\n"; $i++; splice(@$L, $i, $x-1); @@ -478,7 +478,7 @@ sub write_msg { my $O = shift; my $l; - if ((!$lax) && ($O =~ /^>(.*)/) && ($1 ne '-')) { + if ((!$lax) && ($O =~ /^>(.*)/) && ($1 ne '-') && ($1 ne '/dev/null')) { if (!sysopen(OUT, $1, O_EXCL|O_CREAT|O_WRONLY)) { print STDERR "Could not open $1: $!\n"; exit(EX_IOERR); } @@ -604,6 +604,17 @@ sub process_msg { if ($$lines[$x] =~ /^\s*#v([+-])$/) { $verb = $1 eq '+' ? 1 : 0; $vrb[$x] = 1; + } elsif ($diff && $$lines[$x] =~ /^[0-9]+a([0-9]+),([0-9]+)$/) { + # Detect and protect standard diffs. + # Skip and proceed to next line if premature file end or diff line + # numbers implausible (so it might be not a diff at all). + if ($1>$2 || $x+$2-$1+1>$#$lines) { next; } + $vrb[$x] = 1; + for (my $i=0; $i<$2-$1+1; $i++) { $vrb[++$x] = 1; } + } elsif ($diff && $$lines[$x] =~ /^([0-9]+),([0-9]+)c([0-9]+),([0-9]+)$/) { + if ($1!=$3 || $1>$2 || $3>$4 || $x+$2-$1+$4-$3+3>$#$lines) { next; } + $vrb[$x] = 1; + for (my $i=0; $i<$2-$1+$4-$3+3; $i++) { $vrb[++$x] = 1; } } else { $vrb[$x] = $verb; } } @@ -860,6 +871,7 @@ sub process_msg { my $x = 1; for (my $i=$#$lines; $i>=0; $i--) { + if ($vrb[$i]) { last; } if ($$lines[$i] =~ /^$indent/o) { $j++; $k = $i; @@ -945,7 +957,7 @@ sub process_msg { (($mua eq 'mutt' && $$lines[$x] =~ /^\e[^\a]+\a\s*$/o) || $$lines[$x] =~ /^\s*$/o)) { - if ($t<2) { $t++; } else { splice(@$lines, $x, 1); } + if ($t<$cr) { $t++; } else { splice(@$lines, $x, 1); } } else { $t = 0; } } @@ -986,87 +998,89 @@ my $locale = $ENV{'LC_ALL'}?$ENV{'LC_ALL'}: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); my $ifile = '-'; # use STDIN if nothing specified +# temp vals: +my ($_t1, $_t2, $_t3, $_t4, $_t5, $_t6, $_t7, $_t8, $_t9, $_ta, $_tb, $_tc, + $_td) = undef; + # get command line params: -Getopt::Mixed::init('a A=s c d e h i=s k L=s l m M=s o=s P=s p:s r S:i'. - ' s t v w bigq:s body check:s debug>d diff ftr-ad ftr-ml groupwise'. - ' help>h kminl=i kmaxl=i kdiff=i lax-security locale=s max-lines=i'. - ' ms-smart mua>M pgp-short pgp-move pgp-move-vrf reply sani sigsmax:i'. - ' spass version>v'); -while (my ($opt, $val, $pretty) = nextOption()) { - if ($opt eq 'a') { $ad = 1; } - elsif ($opt eq 'A') { $ads = $val; } - elsif ($opt eq 'bigq') { - if ($val !~ /^(?:(\d+)(?:,(\d+))?)?$/) { help(); } - $bigqn = $1?$1:30; - $bigqx = $2?$2:10; - if ($bigqn<=0 || $bigqx<=0 || $bigqn<=$bigqx) { help(); } - } - elsif ($opt eq 'body') { $nohdr = 1; $hdrs = 1; } - elsif ($opt eq 'c') { $cr = 1; } - elsif ($opt eq 'check') { - $check = 1; - while ($val && $val =~ /^([^,\s]+)(?:,(\S+))?$/) { - my $foo = $1; - $val = $2; - - if ($foo =~ /^ratio(?:=(0?\.\d+))?$/) { - $check_ratio = $1?$1:0.75; - } - } - } - elsif ($opt eq 'd') { $sysl = 1; } - elsif ($opt eq 'diff') { $diff = 1; } - elsif ($opt eq 'e') { $elli = 1; } - elsif ($opt eq 'ftr-ad') { $ftr_ad = 1; $ad = 1; } - elsif ($opt eq 'ftr-ml') { $ftr_ml = 1; $ml = 1; } - elsif ($opt eq 'groupwise') { $gw = 1; } - elsif ($opt eq 'i') { $ifile = $val; } - elsif ($opt eq 'k') { $kamm = 1; } - elsif ($opt eq 'kminl') { $kminl = $val; $kamm = 1; } - elsif ($opt eq 'kmaxl') { $kmaxl = $val; $kamm = 1; } - elsif ($opt eq 'kdiff') { $kdiff = $val; $kamm = 1; } - elsif ($opt eq 'L') { $footers = $val; } - elsif ($opt eq 'l') { $ml = 1; } - elsif ($opt eq 'lax-security') { $lax = 1; } - elsif ($opt eq 'locale') { $locale = $val; } - elsif ($opt eq 'm') { $ms = 1; } - elsif ($opt eq 'max-lines') { $maxlines = $val; } - elsif ($opt eq 'ms-smart') { $ms_smart = 1; $ms = 1; } - elsif ($opt eq 'M') { - $mua = lc($val); - - if ($mua eq 'mutt') { - # mutt still displays the message when ^C'ing pgp verification: - $SIG{'INT'} = 'sigint_handler'; - } - } - elsif ($opt eq 'o') { $ofile = $val; } - elsif ($opt eq 'P') { $boun = $val; } - elsif ($opt eq 'p') { $mda = $val ? $val : '1'; } - elsif ($opt eq 'pgp-short') { $pgpshort = 1; } - elsif ($opt eq 'pgp-move') { $pgpmove = 1; } - elsif ($opt eq 'pgp-move-vrf') { $pgpmovevrf = 1; } - elsif ($opt eq 'r') { $hdrs = 1; } - elsif ($opt eq 'reply') { $reply = 1; } - elsif ($opt eq 'S') { $lsig = $val ? $val : $maxsig; } - elsif ($opt eq 's') { $sig = 1; } - elsif ($opt eq 'sani') { $sani = 1; } - elsif ($opt eq 'sigsmax') { $sign = $val ? $val : undef; } - elsif ($opt eq 'spass') { $spass = 1; } - elsif ($opt eq 't') { $trad = 1; } - elsif ($opt eq 'v') { version(); } - elsif ($opt eq 'w') { $trsp = 1; } - else { help(); } +if (!Getopt::Long::GetOptions( + 'a' => \$ad, + 'A=s' => \$ads, + 'bigq:s' => \$_t1, + 'body' => \$_tc, + 'c:i' => \$_td, + 'check:s' => \$_t9, + 'debug|d' => \$sysl, + 'diff' => \$diff, + 'e' => \$elli, + 'ftr-ad' => \$ftr_ad, + 'ftr-ml' => \$ftr_ml, + 'groupwise' => \$gw, + 'help|h' => \$_t2, + 'i=s' => \$ifile, + 'k' => \$kamm, + 'kminl=i' => \$_t3, + 'kmaxl=i' => \$_t4, + 'kdiff=i' => \$_t5, + 'L=s' => \$footers, + 'l' => \$ml, + 'lax-security' => \$lax, + 'locale=s' => \$locale, + 'max-lines:i' => \$maxlines, + 'ms-smart' => \$ms_smart, + 'mua|M=s' => \$_t7, + 'm' => \$ms, + 'o=s' => \$ofile, + 'P=s' => \$boun, + 'p:s' => \$_t8, + 'pgp-short' => \$pgpshort, + 'pgp-move' => \$pgpmove, + 'pgp-move-vrf' => \$pgpmovevrf, + 'r' => \$hdrs, + 'reply' => \$reply, + 'S:i' => \$_t6, + 's' => \$sig, + 'sani' => \$sani, + 'sigsmax:i' => \$_ta, + 'spass' => \$spass, + 't' => \$trad, + 'version|v' => \$_tb, + 'w' => \$trsp + )) { + help(); } -Getopt::Mixed::cleanup(); -if (($ml && $footers eq '')|| # no -l without -L - ($ad && $ads eq '')|| # no -a without -A - ($nohdr && $pgpshort)|| # --body and --pgp-short are oil and water - (($nohdr||$hdrs) && ($sani||$reply))|| # no sanitazing without headers :) - ($ifile eq '')|| # no empty -i - ($ofile eq '')) # no empty -o -{ help(); } +# clean up temp vals: +if (defined $_t1) { + if ($_t1 !~ /^(?:(\d+)(?:,(\d+))?)?$/) { help(); } + $bigqn = $1?$1:30; + $bigqx = $2?$2:10; + if ($bigqn<=0 || $bigqx<=0 || $bigqn<=$bigqx) { help(); } +} +if (defined $_t2) { help(); } +if (defined $_t3) { $kminl = $_t3; $kamm = 1; } +if (defined $_t4) { $kmaxl = $_t4; $kamm = 1; } +if (defined $_t5) { $kdiff = $_t5; $kamm = 1; } +if (defined $_t6) { $lsig = $_t6 ? $_t6 : $maxsig; } +if (defined $_t7) { + $mua = lc($_t7); + # mutt still displays the message when ^C'ing pgp verification: + if ($mua eq 'mutt') { $SIG{'INT'} = 'sigint_handler'; } +} +if (defined $_t8) { $mda = $_t8 ? $_t8 : '1'; } +if (defined $_t9) { + $check = 1; + while ($_t9 && $_t9 =~ /^([^,\s]+)(?:,(\S+))?$/) { + my $foo = $1; + $_t9 = $2; + if ($foo =~ /^ratio(?:=(0?\.\d+))?$/) { $check_ratio = $1?$1:0.75; } + } +} +if (defined $_ta) { $sign = $_ta ? $_ta : undef; } +if (defined $_tb) { version(); } +if (defined $_tc) { $nohdr=1; $hdrs=1; } +if (defined $_td) { $cr = $_td ? $_td : $crshrink; } +if ($ms_smart) { $ms = 1; } if ($mua eq 'mutt') { if (defined $locale && $locale ne '' && $locale ne 'C' && $locale ne 'POSIX') { @@ -1131,6 +1145,14 @@ if ($mua eq 'mutt') { } elsif ($ms_smart || $pgpshort || $pgpmove || $pgpmovevrf) { help(); } + +if (($ml && $footers eq '')|| # no -l without -L + ($ad && $ads eq '')|| # no -a without -A + ($nohdr && $pgpshort)|| # --body and --pgp-short are like oil and water + (($nohdr||$hdrs) && ($sani||$reply))|| # no sanitizing without headers :) + ($ifile eq '')|| # no empty -i + ($ofile eq '')) # no empty -o +{ help(); } # Read message: @@ -1141,19 +1163,17 @@ close IN; # First, check msg length and stop processing if msg is too long: if ((defined $maxlines) && (@message > $maxlines)) { - if ($ofile ne 'NONE') { - if ($mua eq 'mutt') { - my $x = 0; - if (!$nohdr) { - do { $x++; } while ($x<$#message && $message[$x]!~/^$/); - $x++; - } - splice(@message, $x, 0, - ("[---=| Processing by $0 skipped: message too long |=---]\n\n")); + if ($mua eq 'mutt') { + my $x = 0; + if (!$nohdr) { + do { $x++; } while ($x<$#message && $message[$x]!~/^$/); + $x++; } - - write_msg(($mda?'|'.SENDMAIL." $mda":">$ofile"), \@message); + splice(@message, $x, 0, + ("[---=| Processing by $0 skipped: message too long |=---]\n\n")); } + write_msg(($mda?'|'.SENDMAIL." $mda":">$ofile"), \@message); + if ($mua eq 'mutt') { exit(EX_OK); } exit(EX_DATAERR); } @@ -1162,9 +1182,7 @@ if ((defined $maxlines) && (@message > $maxlines)) { process_msg(\@message); # Finally, print clean lines: -if ($ofile ne 'NONE') { - write_msg(($mda?'|'.SENDMAIL." $mda":">$ofile"), \@message); -} +write_msg(($mda?'|'.SENDMAIL." $mda":">$ofile"), \@message); # vim600:set foldmethod=marker: # eof