#!/usr/bin/perl -w
-# $Id: t-prot,v 1.255 2007/09/19 11:32:58 jochen Exp $
+# $Id: t-prot,v 1.307 2010/07/01 16:02:56 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.5';
+use Getopt::Long qw(:config gnu_getopt no_ignore_case);
+use constant VER => '2.99';
use constant REV => '';
-use constant REL => q$Revision: 1.255 $=~m/(\d+(?:\.\d+)+)/;
+use constant REL => q$Revision: 1.307 $=~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';
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
- $footers $ftr_ad $ftr_ml $hdrs $indent $kamm $kdiff $kminl $kmaxl
+ $ad $ads $bigqn $bigqx $boun $check $check_ratio $cr $crshrink $diff $elli
+ $fixind $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 $sig
- $sigint $sign $spass $spass_prefix $sysl $trad $trsp
+ $msg_ratio $mua $nohdr $ofile $pgpshort $pgpmove $pgpmovevrf $reply
+ $sani $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
);
-# Please adjust these vals to your needs (they are no constants because
-# command line can change them or they are used in rexexp's):
+# Please adjust these vals to your needs only if you know what you are
+# doing. They are no constants because command line can change them or
+# they are used in some rexexp.
$0 =~ s!^.*/!!;
$maxsig = 4; # max. valid signature length
$maxlines = undef; # no limit of message lines
-$indent = '>'; # Indent string, regexp to identify a quoted line
+$crshrink = 2; # multiple blank lines are shrunk to $crshrink lines
+$indent = '>'; # Indent string to identify a quoted line
$kminl = 65; # see decomb() for details
$kmaxl = 80;
$kdiff = 20;
$ftr_ml = undef; # too hard on performance to be default
$ofile = '-'; # use STDOUT if nothing is specified
$spass_prefix = 'SPAM: ';
-$check_ratio = .75; # 3/4 tofu is enough not to accept the message
+$check_ratio = 0; # off by default
$msg_quote = "Blocked by $0: This message has been rejected because of a full quote. Please see http://learn.to/quote/ and http://www.escape.de/users/tolot/mutt/ for more info. Have a nice day!\n";
$msg_ratio = "Blocked by $0: This message has been rejected because of excessive quoting. Please see http://learn.to/quote/ and http://www.escape.de/users/tolot/mutt/ for more info. Have a nice day!\n";
# end of user adjusted vals
# 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
+ --fixind fix quotes to adhere to RFC 3676
--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 mailling 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!
--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
+ -m delete MS style TOFU; careful: might be too aggressive
--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
- -S[=n] supress signatures with more than n lines;
- default is $maxsig if n not specified
+ --reply squeeze multiple reply prefixes in subject line
+ -S[n] suppress 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
--spass enable SpamAssassin workaround
-t delete traditional style TOFU
$sigint = 1;
}
+sub sanitize_hdr {
+ # Undoes MIME quoted-printable word encoding.
+ sub qp_decode {
+ my $word = shift;
+ $word =~ tr/_/\x20/;
+ $word =~ s/=DF/ss/og;
+ $word =~ s/=C4/Ae/og;
+ $word =~ s/=D6/Oe/og;
+ $word =~ s/=DC/Ue/og;
+ $word =~ s/=E4/ae/og;
+ $word =~ s/=F6/oe/og;
+ $word =~ s/=FC/ue/og;
+ $word =~ s/=([0-9A-F]{2})/chr(hex $1)/ioge;
+ $word;
+ }
+
+ sub umlauts {
+ my $word = shift;
+ $word =~ s/ä/ae/og;
+ $word =~ s/Ä/Ae/og;
+ $word =~ s/ö/oe/og;
+ $word =~ s/Ö/Oe/og;
+ $word =~ s/ü/ue/og;
+ $word =~ s/Ü/Ue/og;
+ $word =~ s/ß/ss/og;
+ $word;
+ }
+
+ my $H = shift; # array of header lines
+ my $i;
+
+ for ($i=0; $i<$#$H; $i++) {
+ if ($$H[$i] =~ /^subject: /io) {
+ if ($sani) {
+ $$H[$i] =~ s/=\?iso-8859-15?\?q\?([^?]*)\?=/qp_decode($1)/ioge;
+ $$H[$i] =~ s/^subject: *(.*)/"Subject: " . umlauts($1)/ioe;
+ }
+ if ($reply) {
+ $$H[$i] =~ s/^subject: *(?:(?:Re|Antw(?:ort)?|AW|WG): *)+/Subject: Re: /io;
+ }
+
+ $i++;
+ while ($i<$#$H && $$H[$i] =~ /^\s/) {
+ if ($sani) {
+ $$H[$i] =~ s/=\?iso-8859-15?\?q\?([^?]*)\?=/qp_decode($1)/ioge;
+ $$H[$i] =~ s/^\s+(\S.*)/" " . umlauts($1)/ioe;
+ }
+ if ($reply) {
+ $$H[$i] =~ s/^\s+(?:(?:Re|Antw(?:ort)?|AW|WG): *)+/ /io;
+ }
+ $i++;
+ }
+ }
+ elsif ($sani && $$H[$i] =~ /^(?:from|to): /io) {
+ $$H[$i] =~ s/=\?iso-8859-15?\?q\?([^?]*)\?=/qp_decode($1)/ioge;
+
+ $i++;
+ while ($i<$#$H && $$H[$i] =~ /^\s/) {
+ $$H[$i] =~ s/=\?iso-8859-15?\?q\?([^?]*)\?=/qp_decode($1)/ioge;
+ $i++;
+ }
+ }
+ }
+}
+
# remove_footers(): remove any trailing appearance of footers contained
# in the given directory.
sub remove_footers {
for (my $z=0; $z<=$#l; $z++) { chomp($l[$z]); }
if (defined $V) {
- WIPE: for (my $z=scalar(@$L)-scalar(@l); $z>=0; $z--)
- {
+ WIPE: for (my $z=scalar(@$L)-scalar(@l); $z>=0; $z--) {
if (scalar(@l)+$z<=scalar(@$L)) {
my $y = 0;
for(my $x=1; $x<=scalar(@l); $x++) {
- if (index($$L[scalar(@$L)-$x-$z], $l[scalar(@l)-$x])!=0) {
+ if (index($$L[scalar(@$L)-$x-$z],
+ $l[scalar(@l)-$x])!=0) {
$y = 1;
}
}
(index($$L[$x+1], $indent)!=0) &&
($$L[$x+1] !~ /^$/) &&
($$L[$x+1] !~ /^[\s^]/) &&
- ($$L[$x] !~ /-$/) &&
+ ($$L[$x] !~ /-$/) &&
($$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)) &&
+ (index($$L[$x+1], ' ')<0 &&
+ length($$L[$x])+length($$L[$x+1])>$max)) &&
(length($$L[$x])+length($$L[$x+1])<$kmaxl) &&
(length($$L[$x])+length($$L[$x+1])>$kminl) &&
(length($$L[$x])-length($$L[$x+1])>$kdiff) &&
}
# debigq(): Finds big quotes (more than $n lines quoted) and deletes all
-# but $x lines of them.
+# but the last $x lines of them.
sub debigq {
my $L = shift; # array of message lines
my $V = shift; # array with verbatim list
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);
my $uid = 1;
for (my $i=$x+1; $i<scalar(@$L); $i++) {
- if ($pgpshort && index($$L[$i], "gpg: $gpg_aka")==0)
- { $uid++; }
-
- if ($pgpshort && $uid>1 &&
- index($$L[$i], "gpg: $gpg_aka")==0 &&
- index($$L[$i], $from)<0)
- {
- splice(@$L, $i, 1);
- splice(@$V, $i, 1);
- $i--;
+ if ($pgpshort && index($$L[$i], "gpg: $gpg_aka")==0) {
+ $uid++;
+
+ if ($uid>1 && index($$L[$i], $from)<0) {
+ splice(@$L, $i, 1);
+ splice(@$V, $i, 1);
+ $i--;
+ }
}
- elsif ($$L[$i]=~/^(?:\e[^\a]+\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)))
{
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);
}
my (@ads, @hdr, @bo1, @bo2, @ftr, @sig, @vrb, @att) =
((), (), (), (), (), (), (), (), ());
- # First, remove and store lines we might need later...
+ # Remove and store lines we might need later...
# Remove headers:
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);
+ # Sanitize header fields:
+ if ($reply || $sani) { sanitize_hdr(\@hdr); }
+
# Remove ML footers:
remove_footers($lines, \@ftr, $footers, undef, $ftr_ml);
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; }
}
if (index($$lines[$x], $indent)==0) { $y++; }
}
}
- $y = $y/$z;
- if ($y>=$check_ratio) {
+ if ($y/$z>=$check_ratio) {
print $msg_ratio;
exit EX_UNAVAILABLE;
}
}
}
+ # Fix quote markers to adhere to RFC 3676, this changes "> >" to ">> " (if
+ # the default $indent is used). The space after ">" is not mandatory by RFC
+ # but makes the result more readable.
+ if ($fixind) {
+ for ($x=0; $x<scalar(@$lines); $x++) {
+ if (!$vrb[$x] && index($$lines[$x], $indent)==0) {
+ # We match space at the beginning to prevent removal of spaces
+ # directly after the last quote mark.
+ $$lines[$x] =~ /^((\Q$indent\E| )*\Q$indent\E ?)(.*)$/;
+ my $tmp = $1;
+ my $len = length $1;
+ my $rest = $3; # if anything follows after the quote
+ $tmp =~ tr/ //d;
+ $tmp .= ' ' if $rest; # don't create trailing whitespace
+ substr($$lines[$x], 0, $len, $tmp);
+ }
+ }
+ }
+
# See if there is some Kammquoting to fix:
if ($kamm) { decomb($lines, \@vrb); }
my @tofu = ('Original Message',
'Original-Nachricht',
'Ursprüngliche Nachricht',
+ 'Ursprüngliche Nachricht',
'Ursprungliche Nachricht',
'Mensagem original',
'Ursprungligt meddelande',
DONE: for ($x=0; $x<scalar(@$lines); $x++) {
if (!$vrb[$x]) {
foreach my $tmp (@tofu) {
- if (($ms && $$lines[$x] =~ /^-+\s?$tmp\s?-+/) ||
+ if (($ms && $$lines[$x] =~ /^\s?-+\s?$tmp\s?-+/) ||
($gw &&
($$lines[$x] =~ /^>>>[^\<]+<[^\>]+> \d\d?\/\d\d?\/\d\d? \d\d?:\d\d [AP]M >>>/ ||
$$lines[$x] =~ /^>>> On [A-Z][a-z][a-z]?, [A-Z][a-z][a-z]? \d\d?, \d\d\d\d at [ \d]\d:\d\d [AP]M, in message/))) {
if ((!$k) && $$lines[$x] !~ /^\s*$/o &&
((!$mua) ||
($mua eq 'mutt' &&
+ # this line seems not necessary since mutt-1.5.18:
+ $$lines[$x] !~ /^\e[^\a]+\a$/o &&
$$lines[$x] !~
/^(?:\e[^\a]+\a)?(?:\Q$mutt_attachment\E)/o &&
$$lines[$x] !~
my $x = 1;
for (my $i=$#$lines; $i>=0; $i--) {
- if ($$lines[$i] =~ /^$indent/o) {
+ if ($vrb[$i]) { last; }
+ if (index($$lines[$i], $indent)==0) {
$j++;
$k = $i;
}
# Care for trailing whitespaces:
if ($trsp) {
for ($x=0; $x<scalar(@$lines); $x++) {
- if (!$vrb[$x]) { $$lines[$x] =~ s/[\ \t]+$//; }
+ if (!$vrb[$x]) { $$lines[$x] =~ s/[\ \t]+$//o; }
}
}
# Care for punctuation abuse:
if ($elli) {
for ($x=0; $x<scalar(@$lines); $x++) {
- if (!$vrb[$x]) { $$lines[$x] =~ s/(([.?!])\2\2)\2+/$1/g; }
+ if (!$vrb[$x]) { $$lines[$x] =~ s/(([.?!])\2\2)\2+/$1/go; }
}
}
# earlier -- the way it is done right now would screw up the verbatim
# list)
if ($cr) {
+ # When handling regular TOFU above we move the last empty line from
+ # the body to the signature. This prevents the correct removal of
+ # empty lines before a signature (one line less is removed than it
+ # should) when -c and -t are used. This fixes it.
+ if (scalar(@sig) && $sig[0] =~ /^\s*$/) {
+ push(@$lines, shift(@sig));
+ }
+
my $t = 0;
for ($x=scalar(@$lines)-1; $x>=0; $x--) {
- if ((!$vrb[$x]) && $$lines[$x] =~ /^\s*$/) {
- if ($t<2) { $t++; } else { splice(@$lines, $x, 1); }
+ if ((!$vrb[$x]) &&
+ (($mua eq 'mutt' && $$lines[$x] =~ /^\e[^\a]+\a\s*$/o) ||
+ $$lines[$x] =~ /^\s*$/o))
+ {
+ if ($t<$cr) { $t++; } else { splice(@$lines, $x, 1); }
}
else { $t = 0; }
}
($ENV{'LC_MESSAGES'}?$ENV{'LC_MESSAGES'}:$ENV{'LANG'});
# command line switches
-($ad, $ads, $bigqn, $bigqx, $check, $cr, $sysl, $diff, $elli, $footers, $lax,
- $ml, $gw, $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);
+($ad, $ads, $bigqn, $bigqx, $check, $cr, $sysl, $diff, $elli, $fixind, $footers, $lax,
+ $ml, $gw, $ms, $ms_smart, $mda, $mua, $hdrs, $kamm, $lsig, $nohdr, $reply,
+ $sani, $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);
my $ifile = '-'; # use STDIN if nothing specified
+# temp vals:
+my ($_t_bigq, $_t_help, $_t_kminl, $_t_kmaxl, $_t_kdiff, $_t_maxsig, $_t_mua,
+ $_t_redir, $_t_check, $_t_sigsmax, $_t_ver, $_t_nohdr, $_t_cr) = 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 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]+)(?:,(\S+))?$/$2/) {
- my $foo = $1;
-
- if ($foo =~ /^ratio=(0?\.\d+)$/) {
- $check_ratio = $1?$1:1;
- }
- }
- }
- 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 'S') { $lsig = $val ? $val : $maxsig; }
- elsif ($opt eq 's') { $sig = 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' => \$_t_bigq,
+ 'body' => \$_t_nohdr,
+ 'c:i' => \$_t_cr,
+ 'check:s' => \$_t_check,
+ 'debug|d' => \$sysl,
+ 'diff' => \$diff,
+ 'e' => \$elli,
+ 'fixind' => \$fixind,
+ 'ftr-ad' => \$ftr_ad,
+ 'ftr-ml' => \$ftr_ml,
+ 'groupwise' => \$gw,
+ 'help|h' => \$_t_help,
+ 'i=s' => \$ifile,
+ 'k' => \$kamm,
+ 'kminl=i' => \$_t_kminl,
+ 'kmaxl=i' => \$_t_kmaxl,
+ 'kdiff=i' => \$_t_kdiff,
+ 'L=s' => \$footers,
+ 'l' => \$ml,
+ 'lax-security' => \$lax,
+ 'locale=s' => \$locale,
+ 'max-lines:i' => \$maxlines,
+ 'ms-smart' => \$ms_smart,
+ 'mua|M=s' => \$_t_mua,
+ 'm' => \$ms,
+ 'o=s' => \$ofile,
+ 'P=s' => \$boun,
+ 'p:s' => \$_t_redir,
+ 'pgp-short' => \$pgpshort,
+ 'pgp-move' => \$pgpmove,
+ 'pgp-move-vrf' => \$pgpmovevrf,
+ 'r' => \$hdrs,
+ 'reply' => \$reply,
+ 'S:i' => \$_t_maxsig,
+ 's' => \$sig,
+ 'sani' => \$sani,
+ 'sigsmax:i' => \$_t_sigsmax,
+ 'spass' => \$spass,
+ 't' => \$trad,
+ 'version|v' => \$_t_ver,
+ '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 like oil and water
- ($ifile eq '')|| # no empty -i
- ($ofile eq '')) # no empty -o
-{ help(); }
+# clean up temp vals:
+if (defined $_t_bigq) {
+ if ($_t_bigq !~ /^(?:(\d+)(?:,(\d+))?)?$/) { help(); }
+ $bigqn = $1?$1:30;
+ $bigqx = $2?$2:10;
+ if ($bigqn<=0 || $bigqx<=0 || $bigqn<=$bigqx) { help(); }
+}
+if (defined $_t_help) { help(); }
+if (defined $_t_kminl) { $kminl = $_t_kminl; $kamm = 1; }
+if (defined $_t_kmaxl) { $kmaxl = $_t_kmaxl; $kamm = 1; }
+if (defined $_t_kdiff) { $kdiff = $_t_kdiff; $kamm = 1; }
+if (defined $_t_maxsig) { $lsig = $_t_maxsig ? $_t_maxsig : $maxsig; }
+if (defined $_t_mua) {
+ $mua = lc($_t_mua);
+ # mutt still displays the message when ^C'ing pgp verification:
+ if ($mua eq 'mutt') { $SIG{'INT'} = 'sigint_handler'; }
+}
+if (defined $_t_redir) { $mda = $_t_redir ? $_t_redir : '1'; }
+if (defined $_t_check) {
+ $check = 1;
+ while ($_t_check && $_t_check =~ /^([^,\s]+)(?:,(\S+))?$/) {
+ my $foo = $1;
+ $_t_check = $2;
+ if ($foo =~ /^ratio(?:=(0?\.\d+))?$/) { $check_ratio = $1?$1:0.75; }
+ }
+}
+if (defined $_t_sigsmax) { $sign = $_t_sigsmax ? $_t_sigsmax : undef; }
+if (defined $_t_ver) { version(); }
+if (defined $_t_nohdr) { $nohdr=1; $hdrs=1; }
+if (defined $_t_cr) { $cr = $_t_cr ? $_t_cr : $crshrink; }
+if ($ms_smart) { $ms = 1; }
if ($mua eq 'mutt') {
if (defined $locale && $locale ne '' && $locale ne 'C' && $locale ne 'POSIX') {
}
}
-else {
- if ($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:
my @message = <IN>;
close IN;
+# First, check msg length and stop processing if msg is too long:
+if ((defined $maxlines) && (@message > $maxlines)) {
+ 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"));
+ }
+ write_msg(($mda?'|'.SENDMAIL." $mda":">$ofile"), \@message);
+
+ if ($mua eq 'mutt') { exit(EX_OK); }
+ exit(EX_DATAERR);
+}
+
# this should be self-explanatory:
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