]> git.deb.at Git - pkg/t-prot.git/blobdiff - t-prot
Imported Debian patch 2.4-1~bpo1
[pkg/t-prot.git] / t-prot
diff --git a/t-prot b/t-prot
index 446c0eb15c7e8151f668f69ebff319d676d16e40..5141512af69382c96f70b10560b16ed89b34ce51 100755 (executable)
--- a/t-prot
+++ b/t-prot
@@ -1,13 +1,13 @@
 #!/usr/bin/perl -w
-# $Id: t-prot,v 1.227 2005/03/01 15:20:49 jochen Exp $
+# $Id: t-prot,v 1.253 2007/03/09 15:06:04 jochen Exp $
 
 require 5.006;
 use strict;
 use Fcntl qw(O_EXCL O_WRONLY O_CREAT);
 use Getopt::Mixed qw(nextOption);
-use constant VER            => '1.98';
+use constant VER            => '2.4';
 use constant REV            => '';
-use constant REL            => q$Revision: 1.227 $=~m/(\d+(?:\.\d+)+)/;
+use constant REL            => q$Revision: 1.253 $=~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';
@@ -23,9 +23,9 @@ use constant EX_BOUNCE      => EX_UNAVAILABLE;
 use vars qw(
     $ad $ads $bigqn $bigqx $boun $check $check_ratio $cr $diff $elli
     $footers $ftr_ad $ftr_ml $hdrs $indent $kamm $kdiff $kminl $kmaxl
-    $lax $lsig $maxsig $mda $ml $ms $ms_smart $msg_quote $msg_ratio
-    $mua $ofile $pgpshort $pgpmove $pgpmovevrf $sig $sigint $sign
-    $spass $spass_prefix $sysl $trad $trsp
+    $lax $lsig $maxsig $maxlines $mda $ml $ms $ms_smart $msg_quote
+    $msg_ratio $mua $nohdr $ofile $pgpshort $pgpmove $pgpmovevrf $sig
+    $sigint $sign $spass $spass_prefix $sysl $trad $trsp
 
     $gpg_WARNING $gpg_Warning $gpg_Cantcheck $gpg_aka $gpg_bad
     $gpg_expired $gpg_good $gpg_bug
@@ -40,6 +40,7 @@ use vars qw(
 # command line can change them or they are used in rexexp's):
 $0 =~ s!^.*/!!;
 $maxsig         = 4;      # max. valid signature length
+$maxlines       = undef;  # no limit of message lines
 $indent         = '>';    # Indent string, regexp to identify a quoted line
 $kminl          = 65;     # see decomb() for details
 $kmaxl          = 80;
@@ -86,10 +87,12 @@ $gpg_bug                = '... this is a bug (';
 # help(): print help text and exit with appropriate exit code
 sub help {
     print "Usage: $0 [options] 
-  -a              remove ad footers; requires -A
   -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
   --check[=FLAGS] check various criteria, print error message and quit;
                   see man page for details
@@ -111,6 +114,7 @@ sub help {
   --locale=LOCALE internationalization; currently only used with -Mmutt
   -M, --mua=MUA   turn on special treatment for some mail user agents
   -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
@@ -158,12 +162,14 @@ sub remove_footers {
     }
 
     if ($F && scalar(@$L)) {
-        if (!opendir(DIR, $F)) { print STDERR "Could not open $F: $!\n"; exit(EX_IOERR); }
+        if (!opendir(DIR, $F))
+            { print STDERR "Could not open $F: $!\n"; exit(EX_IOERR); }
         my @feet = grep { /^[^.]/ && -f "$F/$_" } readdir DIR;
         closedir DIR;
 
         foreach my $f (@feet) {
-            if (!open(IN, "$F/$f")) { print STDERR "Could not open $F/$f: $!\n"; exit(EX_IOERR); }
+            if (!open(IN, "$F/$f"))
+                { print STDERR "Could not open $F/$f: $!\n"; exit(EX_IOERR); }
             my @l = <IN>;
             close IN;
 
@@ -233,6 +239,7 @@ sub decomb {
         #   underlining some part of the line above (using '^')
         #   nor begin with a whitespace,
         # * the 1st line must not end with a hyphen,
+        # * the 2nd line must not indicate content was deleted,
         # * the 2nd line must not be some mutt(1) commentary,
         # * there must not be a valid word wrap to produce a longer
         #   1st line (if not quoted),
@@ -248,7 +255,8 @@ sub decomb {
             ($$L[$x+1] !~ /^$/) &&
             ($$L[$x+1] !~ /^[\s^]/) &&
             ($$L[$x] !~ /-$/) &&
-            ($mua ne 'mutt' || $$L[$x+1] !~ /^(?:\e.+?\a)?\[-- .* --]/) &&
+            ($$L[$x+1] !~ /^\Q[...]\E\s*$/) &&
+            ($mua ne 'mutt' || $$L[$x+1] !~ /^(?:\e[^\a]+\a)?\[-- /) &&
             (length($$L[$x])+index($$L[$x+1], ' ')>$max ||
                 (index($$L[$x+1], ' ')<0 && length($$L[$x])+length($$L[$x+1])>$max)) &&
             (length($$L[$x])+length($$L[$x+1])<$kmaxl) &&
@@ -307,11 +315,14 @@ sub pgp {
                my $ok = 0;
 
         while ($X<$Z) {
-            if ($$L[$X] =~ /^gpg:\s(?:\Q$gpg_WARNING\E|\Q$gpg_Warning\E|\Q$gpg_bad\E|\Q$gpg_Cantcheck\E|\Q$gpg_expired\E)/o)
+            if (index($$L[$X], "gpg: $gpg_WARNING")==0 ||
+                index($$L[$X], "gpg: $gpg_Warning")==0 ||
+                index($$L[$X], "gpg: $gpg_bad")==0 ||
+                index($$L[$X], "gpg: $gpg_Cantcheck")==0 ||
+                index($$L[$X], "gpg: $gpg_expired")==0 ||
+                index($$L[$X], "gpg: $gpg_bug")==0)
                 { return 0; }
-            if ($$L[$X] =~ /^gpg:\s\Q$gpg_bug/o)
-                { return 0; }
-            if ($$L[$X] =~ /^gpg:\s\Q$gpg_good/o)
+            if (index($$L[$X], "gpg: $gpg_good")==0)
                 { $ok = 1; }
             $X++;
         }
@@ -329,32 +340,35 @@ sub pgp {
     for (my $x=0; $x<scalar(@$L); $x++) {
         if ($$V[$x]) { next; }
 
-        if ($$L[$x]=~/^(?:\e.+?\a)?(?:\Q$mutt_pgpoutstart\E)/o)
+        if ($$L[$x]=~/^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpoutstart\E)/o)
         {
             my $from;
             for (my $m=0; $m<scalar(@$H); $m++) {
-                if ($$H[$m] =~ /^From:/) {
+                if (index($$H[$m], 'From:')==0) {
                     $from = $$H[$m];
                     $m++;
-                    while ($$H[$m] =~ /^\s/) { $from .= $$H[$m]; $m++; }
+                    while (exists($$H[$m]) && $$H[$m] =~ /^\s/)
+                        { $from .= $$H[$m]; $m++; }
                     last;
                 }
             }
-            ($from) = $from=~m/([a-z\d][a-z_\d\+-\.]*\@(?:[a-z_\d\+-\.]+\.)+[a-z]{2,})/i;
+            ($from) = $from=~m/(\w[\w.+-]*@(?:[\w.+-]+\.)+[A-Za-z]{2,})/;
 
             my $uid = 1;
 
             for (my $i=$x+1; $i<scalar(@$L); $i++) {
-                if ($pgpshort && $$L[$i] =~ /^gpg:\s\Q$gpg_aka/o) { $uid++; }
+                if ($pgpshort && index($$L[$i], "gpg: $gpg_aka")==0)
+                    { $uid++; }
 
                 if ($pgpshort && $uid>1 &&
-                    $$L[$i] =~ /^gpg:\s\Q$gpg_aka/o && $$L[$i] !~ /\Q$from/)
+                    index($$L[$i], "gpg: $gpg_aka")==0 &&
+                    index($$L[$i], $from)<0)
                 { 
                     splice(@$L, $i, 1);
                     splice(@$V, $i, 1);
                     $i--;
                 }
-                elsif ($$L[$i]=~/^(?:\e.+?\a)?(?:\Q$mutt_pgpoutend\E)/o)
+                elsif ($$L[$i]=~/^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpoutend\E)/o)
                 {
                     if ($pgpmove ||
                         ($pgpmovevrf && (!$sigint) && verified($L, $x+1, $i)))
@@ -370,7 +384,12 @@ sub pgp {
             }
         }
         elsif ($tmp &&
-            $$L[$x]=~/^(?:\e.+?\a)?(?:\Q$mutt_pgpencrypted\E|\Q$mutt_pgpclearsigned\E|\Q$mutt_pgpsigned\E)/o)
+            $$L[$x] =~ /^
+                        (?:\e[^\a]+\a)?
+                        (?:\Q$mutt_pgpencrypted\E  |
+                           \Q$mutt_pgpclearsigned\E|
+                           \Q$mutt_pgpsigned\E)
+                       /ox)
         {
             splice(@$L, $x+1, 0, @{$tmp[$tmp]});
             for (my $i=$x; $i<scalar(@{$tmp[$tmp]}); $i++) {
@@ -423,23 +442,40 @@ sub process_msg {
 
     # First, remove and store lines we might need later...
     # Remove headers:
-    for ($x=0; $x<$#$lines; $x++) { if (@$lines[$x] =~ /^$/) { last; }; }
-    @hdr = @$lines[0..$x];
-    splice(@$lines, 0, $x+1);
+    if (!$nohdr) {
+        for ($x=0; $x<$#$lines; $x++) { if (@$lines[$x] =~ /^$/) { last; }; }
+
+        # check body length and stop processing silently if msg is too long:
+        if ((defined $maxlines) && (@$lines-$x > $maxlines)) {
+            return;
+        }
+
+        @hdr = @$lines[0..$x];
+        splice(@$lines, 0, $x+1);
+    }
+    elsif ((defined $maxlines) && (@$lines > $maxlines)) {
+        # check body length and stop processing silently if msg is too long:
+        return;
+    }
     # remember the original body lines count
     my $linecount = scalar(@$lines);
 
+    # Remove ML footers:
+    remove_footers($lines, \@ftr, $footers, undef, $ftr_ml);
+
+    # Remove ad footers:
+    remove_footers($lines, \@ads, $ads, undef, $ftr_ad);
 
     # See if we have a multipart content type. If yes, see if it is already
-    # ripped (e.g. by mutt(1)), otherwise only leave the first part if it
-    # is plain text (if not, we are done - non-text messages are not our
-    # business).
+    # ripped (e.g. by you MUA, assuming it does not get special treatment with
+    # --mua=foo), otherwise only leave the first part if it is plain text (if
+    # not, we are done - non-text messages are not our business).
     if ($mua ne 'mutt') { 
         for ($x=0; $x<scalar(@hdr); $x++) {
-            if ($hdr[$x] =~ /^Content-Type:\s+(.*)$/i) {
+            if ($hdr[$x] =~ /^Content-[Tt]ype:\s+(.*)$/) {
                 my $foo = $1;
 
-                if ($foo =~ /^multipart\//i) {
+                if ($foo =~ m!^multipart/!) {
                     undef $foo;
 
                     if ($hdr[$x] =~ /\Wboundary="([^"]+)"/i) { $foo = $1; }
@@ -459,13 +495,13 @@ sub process_msg {
                             my $bar = 'text/plain';
                             for ($x++; $x<@$lines && $$lines[$x]!~/^$/; $x++)
                             {
-                                if ($$lines[$x] =~ /^Content-Type:\s+(.*)/i) { 
+                                if ($$lines[$x] =~ /^Content-[Tt]ype:\s+(.*)/) { 
                                     $bar = $1;
                                 }
                             }
                             if ($x>=scalar(@$lines)) { exit(EX_DATAERR); }
 
-                            if ($bar =~ /^text\/plain/i) {
+                            if ($bar =~ m!^text/plain!) {
                                 my $z;
                                 for ($z=1; $x+$z<@$lines; $z++) {
                                     if (index($$lines[$x+$z], '--'.$foo)==0) {
@@ -481,6 +517,12 @@ sub process_msg {
                                 }
                                 @bo1 = @$lines[0..$x];
                                 splice(@$lines, 0, $x+1);
+
+                                # remove mailing list and ad footers within this
+                                # attachment:
+                                remove_footers($lines, \@ftr, $footers, undef, $ftr_ml);
+                                remove_footers($lines, \@ads, $ads, undef, $ftr_ad);
+
                                 last;
                             }
                             else { 
@@ -512,7 +554,7 @@ sub process_msg {
         for ($x=0; $x<scalar(@$lines); $x++) {
             if (!$vrb[$x]) {
                 $z++;
-                if ($$lines[$x] =~ /^$indent/) { $y++; }
+                if (index($$lines[$x], $indent)==0) { $y++; }
             }
         }
         $y = $y/$z;
@@ -523,12 +565,6 @@ sub process_msg {
         }
     }
 
-    # Remove ML footers:
-    remove_footers($lines, \@ftr, $footers, undef, $ftr_ml);
-
-    # Remove ad footers:
-    remove_footers($lines, \@ads, $ads, undef, $ftr_ad);
-
     if ($mua eq 'mutt') {
         # See if we find pgp output generated by mutt before we scramble
         # the thing. If yes, see if we can beautify it.
@@ -542,17 +578,28 @@ sub process_msg {
             if ($vrb[$x]) { next; }
             # The following regexp's are quite ugly because for most users
             # these lines are coloured using termcap... (bah!)
-            if (($$lines[$x] =~ /^(?:\e.+?\a)?\Q$mutt_attachment\E(\d+)(?::.*)? \-\-\]/o &&
+            if (($$lines[$x] =~
+                     /^(?:\e[^\a]+\a)?\Q$mutt_attachment\E(\d+)/o &&
                     (($1 ne '1') ||
                     ($x<$#$lines &&
-                        $$lines[$x+1] !~ /^(?:\e.+?\a)?(?:\Q$mutt_contenttype\E)(?:text\/plain|application\/pgp)/io))) ||
-                ($$lines[$x] =~ /^(?:\e.+?\a)?(?:\Q$mutt_pgpsigned\E|\Q$mutt_pgpclearsigned\E|\Q$mutt_pgpencrypted\E)/o))
+                        $$lines[$x+1] !~ m!^
+                            (?:\e[^\a]+\a)?
+                            (?:\Q$mutt_contenttype\E)
+                            (?:text/plain|application/pgp)
+                        !ox))) ||
+                ($$lines[$x] =~ /^
+                    (?:\e[^\a]+\a)?
+                    (?:\Q$mutt_pgpsigned\E     |
+                       \Q$mutt_pgpclearsigned\E|
+                       \Q$mutt_pgpencrypted\E)
+                /ox))
             { 
                 # Strip attachments to prepare further processing
                 unshift(@att, @$lines[$x..$#$lines]);
                 splice(@$lines, $x);
                 # Try to fix trailing empty lines
-                while (scalar(@$lines) && $$lines[$#$lines] =~ /^(?:\e.+?\a)?\s*$/) { 
+                while (scalar(@$lines) && $$lines[$#$lines] =~
+                    /^(?:\e[^\a]+\a)?\s*$/) { 
                     unshift(@att, pop(@$lines));
                 }
 
@@ -579,8 +626,12 @@ sub process_msg {
                 # situations.
                 # The following regexp is quite ugly because for most
                 # users the line is coloured using termcap... (bah!)
-                if ($att[$x]=~/^(?:\e.+?\a)?\Q$mutt_attachment\E\d+.* --\]/o &&
-                    $att[$x+1] =~ /^(?:\e.+?\a)?(?:\Q$mutt_contenttype\E)message\/rfc822/o)
+                if ($att[$x] =~
+                        /^(?:\e[^\a]+\a)?\Q$mutt_attachment\E\d+/o &&
+                    $att[$x+1] =~ m!^
+                        (?:\e[^\a]+\a)?
+                        (?:\Q$mutt_contenttype\E) (?:message/rfc822|multipart/alternative)
+                    !ox)
                 {
                     $x += 2;
                     while ($att[$x] !~ /^\s*$/) { $x++; }
@@ -598,36 +649,44 @@ sub process_msg {
     # Remove signature:
     if (scalar(@$lines)) { 
         my $sn = 0;
+        my $chk_empty = 1;
+        my $empty = 0;
+
         for ($x = $#$lines; $x>=0; $x--) {
-            if ((!$vrb[$x]) && $$lines[$x] =~ /^-- $/) {
-                if ($diff) {
-                    for (my $i=1; $x+$i+1<scalar(@$lines); $i++) {
-                        if ($$lines[$x+$i] =~ /^\-\-\-\s+\S/ &&
-                            $$lines[$x+$i+1] =~ /^\+\+\+\s+\S/)
-                        {
-                            $sig = 0;
-                            unshift(@sig, @$lines[$x..$#$lines]);
-                            splice(@$lines, $x);
-                            last;
+            if (!$vrb[$x]) {
+                if ($$lines[$x] =~ /^-- $/) {
+                    if ($diff) {
+                        for (my $i=1; $x+$i+1<scalar(@$lines); $i++) {
+                            if ($$lines[$x+$i] =~ /^-{3}\s+\S/ &&
+                                $$lines[$x+$i+1] =~ /^\+{3}\s+\S/)
+                            {
+                                $sig = 0;
+                                unshift(@sig, @$lines[$x..$#$lines]);
+                                splice(@$lines, $x);
+                                last;
+                            }
+                        }
+                        if (scalar(@sig)) {
+                            if (defined($sign) && ++$sn==$sign) { last; } else { next; }
                         }
                     }
-                    if (scalar(@sig)) {
-                        if (defined($sign) && ++$sn==$sign) { last; } else { next; }
-                    }
-                }
 
-                if ($sig || ($lsig && ($#$lines-$x>$lsig))) {
-                    if ($lsig && !$sig) {
-                        unshift(@sig, "[---=| Overlong signature removed by $0: " .
-                            (scalar(@$lines)-$x) . " lines snipped |=---]\n");
+                    if ($sig || ($lsig && ($#$lines-$x-$empty>$lsig))) {
+                        if ($lsig && !$sig) {
+                            unshift(@sig, "[---=| Overlong signature removed by $0: " .
+                                (scalar(@$lines)-$x) . " lines snipped |=---]\n");
+                        }
+                        splice(@$lines, $x);
                     }
-                    splice(@$lines, $x);
-                }
-                else {
-                    unshift(@sig, @$lines[$x..$#$lines]);
-                    splice(@$lines, $x);
+                    else {
+                        unshift(@sig, @$lines[$x..$#$lines]);
+                        splice(@$lines, $x);
+                    }
+                    if (defined($sign) && ++$sn==$sign) { last; } else { next; }
                 }
-                if (defined($sign) && ++$sn==$sign) { last; } else { next; }
+                # any trailing newlines?
+                elsif ($chk_empty && $$lines[$x] =~ /^\s*$/) { $empty++; }
+                elsif ($chk_empty) { $chk_empty = 0; }
             }
         }
     }
@@ -640,6 +699,7 @@ sub process_msg {
     if ($ms) {
         # bloat this array if you want more internationalization:
         my @tofu = ('Original Message',
+                    'Original-Nachricht',
                     'Ursprüngliche Nachricht',
                     'Ursprungliche Nachricht',
                     'Mensagem original',
@@ -665,16 +725,21 @@ sub process_msg {
                 if ((!$k) && $$lines[$x] !~ /^\s*$/o &&
                     ((!$mua) ||
                      ($mua eq 'mutt' &&
-                         $$lines[$x] !~ /^(?:\e.+?\a)?(?:\Q$mutt_attachment\E)/o &&
-                         $$lines[$x] !~ /^(?:\e.+?\a)?(?:\Q$mutt_contenttype\E)/o)) &&
-                    ((!$spass) || $$lines[$x]!~/^\Q$spass_prefix/o))
+                         $$lines[$x] !~
+                             /^(?:\e[^\a]+\a)?(?:\Q$mutt_attachment\E)/o &&
+                         $$lines[$x] !~
+                             /^(?:\e[^\a]+\a)?(?:\Q$mutt_contenttype\E)/o)) &&
+                    ((!$spass) || index($$lines[$x], $spass_prefix)!=0))
                 {
                     if ($mua eq 'mutt' && (!$tmp) &&
-                        $$lines[$x] =~ /^(?:\e.+?\a)?(?:\Q$mutt_pgpoutstart\E)/o) {
+                        $$lines[$x] =~
+                             /^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpoutstart\E)/o) {
                         $tmp = 1; 
                     } elsif ($mua eq 'mutt' && $tmp && 
-                        ($$lines[$x] =~ /^(?:\e.+?\a)?(?:\Q$mutt_beginsigned\E)/o ||
-                         $$lines[$x] =~ /^(?:\e.+?\a)?(?:\Q$mutt_pgpclearsigstart\E)/o)) {
+                        ($$lines[$x] =~
+                             /^(?:\e[^\a]+\a)?(?:\Q$mutt_beginsigned\E)/o ||
+                         $$lines[$x] =~
+                             /^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpclearsigstart\E)/o)) {
                         $tmp = 0;
                     } elsif (!$tmp) {
                         $k = 1;
@@ -692,17 +757,19 @@ sub process_msg {
             my $p = 0;    # levels of pgp signed parts
 
             for (my $i=$x+1; $i<scalar(@$lines); $i++) {
-                if ($$lines[$i] =~ /^(?:\e.+?\a)?(?:\Q$mutt_pgpclearsigstart\E)/o) {
+                if ($$lines[$i] =~
+                        /^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpclearsigstart\E)/o) {
                     $p++;
                 }
             }
             if ($p) {
                 STAIRS: for (my $i=0; $i<scalar(@att); $i++) {
-                    if ($p==0 && $att[$i] =~ /^(?:\e.+?\a)?\[\-\-\ /o) {
+                    if ($p==0 && $att[$i] =~ /^(?:\e[^\a]+\a)?\[-- /o) {
                         splice(@att, 0, $i);
                         unshift(@att, "\n");
                         goto CLEAN;
-                    } elsif ($att[$i] =~ /^(?:\e.+?\a)?(?:\Q$mutt_pgpclearsigned\E)/o) {
+                    } elsif ($att[$i] =~
+                            /^(?:\e[^\a]+\a)?(?:\Q$mutt_pgpclearsigned\E)/o) {
                         splice(@att, 0, $i+1);
                         $p--;
                         goto STAIRS;
@@ -800,7 +867,7 @@ sub process_msg {
     # Care for punctuation abuse:
     if ($elli) {
         for ($x=0; $x<scalar(@$lines); $x++) { 
-            if (!$vrb[$x]) { $$lines[$x] =~ s/(([.?!])\2\2)\2+/$1/eg; }
+            if (!$vrb[$x]) { $$lines[$x] =~ s/(([.?!])\2\2)\2+/$1/g; }
         }
     }
 
@@ -842,20 +909,21 @@ sub process_msg {
 
 
 # environment
-my $locale = $ENV{'LC_ALL'}?$ENV{'LC_ALL'}:($ENV{'LC_MESSAGES'}?$ENV{'LC_MESSAGES'}:$ENV{'LANG'});
+my $locale = $ENV{'LC_ALL'}?$ENV{'LC_ALL'}:
+                 ($ENV{'LC_MESSAGES'}?$ENV{'LC_MESSAGES'}:$ENV{'LANG'});
 
 # command line switches
 ($ad, $ads, $bigqn, $bigqx, $check, $cr, $sysl, $diff, $elli, $footers, $lax,
-    $ml, $ms, $ms_smart, $mda, $mua, $hdrs, $kamm, $lsig, $sig, $sigint,
+    $ml, $ms, $ms_smart, $mda, $mua, $hdrs, $kamm, $lsig, $nohdr, $sig, $sigint,
     $spass, $trad, $trsp) =
-    (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, 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
 
 # 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 check:s debug>d diff ftr-ad ftr-ml help>h kminl=i'.
-    ' kmaxl=i kdiff=i lax-security locale=s ms-smart mua>M pgp-short'.
-    ' pgp-move pgp-move-vrf sigsmax:i spass version>v');
+    ' s t v w bigq:s body check:s debug>d diff ftr-ad ftr-ml 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 sigsmax:i spass version>v');
 while (my ($opt, $val, $pretty) = nextOption()) {
     if    ($opt eq 'a')     { $ad = 1; }
     elsif ($opt eq 'A')     { $ads = $val; }
@@ -865,6 +933,7 @@ while (my ($opt, $val, $pretty) = nextOption()) {
         $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;
@@ -891,6 +960,7 @@ while (my ($opt, $val, $pretty) = nextOption()) {
     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);
@@ -919,6 +989,7 @@ while (my ($opt, $val, $pretty) = nextOption()) {
 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 like oil and water
     ($ifile eq '')||             # no empty -i
     ($ofile eq ''))              # no empty -o
 { help(); }
@@ -931,57 +1002,57 @@ if ($mua eq 'mutt') {
             Locale::gettext::textdomain('mutt');
             ($mutt_attachment) =
                 Locale::gettext::gettext("[-- Attachment #%d") =~
-                m/^([^%]*)/o;
+                m/^([^%]*)/;
             ($mutt_contenttype) =
                 Locale::gettext::gettext("[-- Type: %s/%s, Encoding: %s, Size: %s --]\n") =~
-                m/^([^%]*)/o;
+                m/^([^%]*)/;
             ($mutt_pgpsigned) =
                 Locale::gettext::gettext("[-- End of signed data --]\n")  =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($mutt_beginsigned) =
                 Locale::gettext::gettext("[-- The following data is signed --]\n\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($mutt_pgpclearsigned) =
                 Locale::gettext::gettext("[-- END PGP SIGNED MESSAGE --]\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($mutt_pgpclearsigstart) =
                 Locale::gettext::gettext("[-- BEGIN PGP SIGNED MESSAGE --]\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($mutt_pgpencrypted) =
                 Locale::gettext::gettext("[-- End of PGP/MIME encrypted data --]\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($mutt_pgpoutstart) =
                 Locale::gettext::gettext("[-- PGP output follows (current time: %c) --]\n") =~
-                m/^([^%]*)/o;
+                m/^([^%]*)/;
             ($mutt_pgpoutend) =
                 Locale::gettext::gettext("[-- End of PGP output --]\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
 
             Locale::gettext::textdomain('gnupg');
             ($gpg_WARNING) =
                 Locale::gettext::gettext("WARNING: using insecure random number generator!!\n") =~
-                m/^(.*?: )/o;
+                m/^([^:]*: )/;
             ($gpg_Warning) =
                 Locale::gettext::gettext("WARNING: message was encrypted with a weak key in the symmetric cipher.\n") =~
-                m/^(.*?: )/o;
+                m/^([^:]*: )/;
             ($gpg_Cantcheck) =
                 Locale::gettext::gettext("Can't check signature: %s\n") =~
-                m/^([^%]*)/o;
+                m/^([^%]*)/;
             ($gpg_aka) =
                 Locale::gettext::gettext((' 'x16).'aka "%s"') =~
-                m/^(.*?)["«%]/o;
+                m/^([^"«%]*)["«%]/;
             ($gpg_bad) =
                 Locale::gettext::gettext('BAD signature from "%s"') =~
-                m/^(.*?)["«%]/o;
+                m/^([^"«%]*)["«%]/;
             ($gpg_expired) =
                 Locale::gettext::gettext("Note: This key has expired!\n") =~
-                m/^(.*?)\n/mo;
+                m/^(.*)\n/m;
             ($gpg_good) =
                 Locale::gettext::gettext('Good signature from "%s"') =~
-                m/^(.*?)["«%]/o;
+                m/^(([^"«%]*))["«%]/;
             ($gpg_bug) =
                 Locale::gettext::gettext("... this is a bug (%s:%d:%s)\n") =~
-                m/^([^%]*)/o;
+                m/^([^%]*)/;
         }
     }
 
@@ -992,7 +1063,8 @@ else {
 
 
 # Read message:
-if (!open(IN, $ifile)) { print STDERR "Could not open $ifile: $!\n"; exit(EX_IOERR); }
+if (!open(IN, $ifile))
+    { print STDERR "Could not open $ifile: $!\n"; exit(EX_IOERR); }
 my @message = <IN>;
 close IN;