Default to fcntl locking for AIX, Cygwin, and Linux. Without it
[mmh] / docs / contrib / replyfilter
index 193dd40..2e98794 100755 (executable)
@@ -37,12 +37,23 @@ use MIME::Base64;
 use Encode;
 
 #
-# The program we use to format "long" text
+# The program we use to format "long" text.  Should be capable of reading
+# from standard input and sending the formatted text to standard output.
 #
 
 $filterprogram = 'par';
 
 #
+# If the above filter program has problems with some input, use the following
+# regular expression to remove any problematic input.  In this example we
+# filter out the UTF-8 non-breaking space (U+00A0) because that makes par
+# mangle the output.  Uncomment this if this ends up being a problem for
+# you, or feel free to add others.
+#
+
+#%filterreplace = ( "\N{U+a0}" => " " );
+
+#
 # Our output character set.  This script assumes a UTF-8 locale, but if you
 # want to run under a different locale the change it here.
 #
@@ -152,7 +163,7 @@ sub process_text (*$$;$)
        my ($input, $encoding, $charset, $boundary) = @_;
        my $text, $filterpid, $prefixpid, $finread, $finwrite;
        my $foutread, $foutwrite, $decoder, $ret, $filterflag;
-       my @text = ( '' ), $maxline = 0;
+       my $text, $maxline = 0;
 
        #
        # In the simple case, just spit out the text prefixed by the
@@ -160,15 +171,28 @@ sub process_text (*$$;$)
        #
 
        if ($encoding eq '7bit' || $encoding eq '8bit') {
+               #
+               # Switch the character set to whatever is specified by
+               # the MIME message
+               #
+               binmode($input, ":encoding($charset)");
                while (<$input>) {
                        $ret = match_boundary($_, $boundary);
                        if (defined $ret) {
+                               binmode($input, ':encoding(us-ascii)');
                                return $ret;
                        }
                        print $quoteprefix, $_;
                }
                return 'EOF';
        } else {
+               #
+               # If we've got some other encoding, the input text is almost
+               # certainly US-ASCII
+               #
+
+               binmode($input, ':encoding(us-ascii)');
+
                $decoder = find_decoder($encoding);
                if (! defined $decoder) {
                        return 'EOF';
@@ -177,26 +201,30 @@ sub process_text (*$$;$)
 
        #
        # Okay, assume that the encoding will make it so that we MIGHT need
-       # to filter it.  Read it in; if it's too long, filter it.
+       # to filter it.  Read it in; if the lines are too long, filter it
        #
 
+       my $chardecode = find_encoding($charset);
+
        while (<$input>) {
-               my $line, $len;
+               my @lines, $len;
 
                last if ($ret = match_boundary($_, $boundary));
 
-               $line = decode($charset, &$decoder($_));
+               $text .= $_;
 
-               if (substr($text[$#text], -1, 1) eq "\n") {
-                       push @text, $line;
-               } else {
-                       $text[$#text] .= $line;
-               }
-               if (($len = length($text[$#text])) > $maxline) {
-                       $maxline = $len;
-               }
        }
 
+       binmode($input, ':encoding(us-ascii)');
+
+       $text = $chardecode->decode(&$decoder($text));
+
+       grep {
+               my $len;
+               if (($len = length) > $maxline) {
+                       $maxline = $len;
+               }} split(/^/, $text);
+
        if (! defined $ret) {
                $ret = 'EOF';
        }
@@ -205,7 +233,9 @@ sub process_text (*$$;$)
                #
                # These are short enough; just output it now as-is
                #
-               print STDOUT @text;
+               foreach my $line (split(/^/, $text)) {
+                       print STDOUT $quoteprefix, $line;
+               }
                return $ret;
        }
 
@@ -291,7 +321,13 @@ sub process_text (*$$;$)
        # Send our input to the filter program
        #
 
-       print $finwrite @text;
+       if (%filterreplace) {
+               foreach my $match (keys %filterreplace) {
+                        $text =~ s/$match/$filterreplace{$match}/g;
+               }
+       }
+
+       print $finwrite $text;
 
        close($finwrite);
        waitpid $filterpid, 0;
@@ -627,6 +663,8 @@ sub match_boundary($$)
 {
        my ($_, $boundary) = @_;
 
+       return if ! defined $boundary;
+
        if (substr($_, 0, 2) eq '--') {
                s/[ \t\r\n]+\Z//;
                if ($_ eq "--$boundary") {