]> git.deb.at Git - pkg/t-prot.git/blobdiff - t-prot
Imported Upstream version 2.97
[pkg/t-prot.git] / t-prot
diff --git a/t-prot b/t-prot
index bb2a0c239de4cfe3b298f7df91e392d25bde5aab..1d51b3bb356d5b730b1f4e0fc17e2aa76557df12 100755 (executable)
--- a/t-prot
+++ b/t-prot
@@ -1,13 +1,13 @@
 #!/usr/bin/perl -w
 #!/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);
 
 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 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';
 # 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(
 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
     $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
 $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;
 $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] 
 # 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
   -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
   --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
   -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\"
   -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
   --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!
                   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
   -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
   --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
   -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;
 
                 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);
                     "$x lines snipped |=---]\n";
                 $i++;
                 splice(@$L, $i, $x-1);
@@ -478,7 +478,7 @@ sub write_msg {
     my $O = shift;
     my $l;
 
     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);
         }
         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;
         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; }
     }
 
         } else { $vrb[$x] = $verb; }
     }
 
@@ -860,6 +871,7 @@ sub process_msg {
         my $x = 1;
 
         for (my $i=$#$lines; $i>=0; $i--) {
         my $x = 1;
 
         for (my $i=$#$lines; $i>=0; $i--) {
+            if ($vrb[$i]) { last; }
             if ($$lines[$i] =~ /^$indent/o) {
                 $j++;
                 $k = $i;
             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))
             { 
                 (($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; }
         }
             }
             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
 
     (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:
 # 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') {
 
 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(); }
 
 }
 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:
 
 
 # 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)) {
 
 # 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);
 }
     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:
 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
 
 # vim600:set foldmethod=marker:
 # eof