Hi Pavel,

On Sun, 11 Feb 2001, Pavel Roskin wrote:

> I have applied the following patch to your mailfs script. Now it can find
> dates for all messages in my inbox, even those with Y2K bugs and tabs
> after "Date:".

your message surprises me: to my knowledge the mailfs that is
distributed with mc doesn't even work with current versions of
the "Midnight Commander" (the script used to return the number of
lines in the message as the "file size". Starting with 4.5.x, mc
takes that "file size" serious and only displays that many bytes
- has this changed again?). Already in October 1999, I had posted
some patches to fix this and some other things (like providing a
fallback date ;-) to thist list and asked, that somebody with CVS
write access apply these patches, which never happened. In case
somebody is still interested, I attach the "mailfs", that I am
currently using below.

As far as the date parsing is concerned, I personally don't think
that trying to parse all date formats out there would be a good
idea - there are just too many variations. To get this right
would require much more code than the whole rest of the script.
The regex for date parsing in my script was only intended as a
last ressort - if available, the Date::Parse module will be used
instead (which does a much better - but still not perfect - job
parsing "exotic" date formats).

By the way, there also is a little bug in vfs.c, that causes mc
to display an incorrect year number when an extfs lists filedates
in ctime format. An (admittedly ugly) patch is included below.

Regards,
                  Peter Daum


 - - - - - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - -

--- vfs.c.org   Sun Feb 11 18:21:12 2001
+++ vfs.c       Sun Feb 11 18:23:36 2001
@@ -1523,6 +1523,7 @@
     struct tm tim;
     int d[3];
     int        got_year = 0;
+    int        got_year2 = 0;

     /* Let's setup default time values */
     tim.tm_year = current_year;
@@ -1596,7 +1597,7 @@

        /* This is a special case for ctime() or Mon DD YYYY hh:mm */
        if(is_num (idx) && (columns[idx+1][0]) &&
-           ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
+           ((got_year2 = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim)))
                idx++; /* time & year or reverse */
        } /* only time or date */
     }
@@ -1609,7 +1610,7 @@
      * This does not check for years before 1900 ... I don't know, how
      * to represent them at all
      */
-    if (!got_year &&
+    if (!(got_year||got_year2) &&
        current_mon < 6 && current_mon < tim.tm_mon &&
        tim.tm_mon - current_mon >= 6)

 - - - - - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - -

#!/usr/bin/perl
# $Id: mailfs,v 1.2 2000/05/15 19:02:37 gator Exp $

# MC extfs for (possibly compressed) Berkeley style mailbox files
# Peter Daum <[EMAIL PROTECTED]> (Jan 1998, mc-4.1.24)
# (minor changes Oct 1999 for mc-4.5.40)
# experimental copyin+rm opereation added May 2000

$allow_write=0;               # set to 1 to enable writing
# (Beware: This will not work as you expect - After insertions or
# deletions, what mc displays will not be consistent with the actual
# state of the file on disk, because "filenames" are not meaningful
# inside mail folders)


$zcat="zcat";                 # gunzip to stdout
$bzcat="bzip2 -dc";           # bunzip2 to stdout
$file="file";                 # "file" command
$TZ='GMT';                    # default timezone (for Date module)

$max_fn=22;                   # maximum length of generated filename
$max_fn-=4;

# For decent date parsing, get CPAN/authors/id/GBARR/TimeDate-1.x.tar.gz
if (eval "require Date::Parse") { # fancy date parsing available?
    import Date::Parse;
    $parse_date=
        sub {
            local $_ =localtime(str2time($_[0],$TZ));
            s/^... (.+) (\d\d:\d\d):\d\d (\d\d\d\d)$/$1 $3 $2/;
            return $_;
        }
} else {                        # use "light" version
    $parse_date= sub {
        # assumes something like: Mon, 5 Jan 1998 16:08:19 +0200 (GMT+0200)
        # if you have mails with another date format, add it here
        if (/(\d\d?) ([A-Z][a-z][a-z]) (\d\d\d\d) (\d\d:\d\d):\d\d/) {
            return "$2 $1 $3 $4";
        }
    }
}

sub get_user_name {
    $ENV{USER}||getlogin||getpwuid($<) || "nobody";
}

sub process_header {
    while (<IN>) {
        $size += length;
        last if /^$/ or eof;
        if (/^Date: (.*)$/) {
            $date=&$parse_date($1);
        } elsif (/^Subject: (.*)$/) {
            $subj=$1;
            $subj=~ s/^(re: ?)+//gi;  # no leading Re:
            $subj=~ tr/a-zA-Z0-9//cd; # strip all "special" characters
        } elsif (/^From: .*?(\w+)\@/) {
            $from=$1;
        } elsif (/^To: .*?(\w+)\@/) {
            $to=$1;
        }
    }
}

sub print_dir_line {
    $from=$to if ($from eq $user); # otherwise, it would look pretty boring

    # dummy date, in case the date couldn't be parsed:
    $date = "Jan  01 1970 11:11" unless $date;

    printf "-r-------- 1 $< $< %d %s %3.3d_%.${max_fn}s\n",
    $size, $date, $msg_nr, "${from}_${subj}";
}

sub mailfs_list {
    my $blank = 1;
    $user=get_user_name;

    exit if -z IN;              # empty, exit immediately
    while(1) {
        $_=<IN>;
        if (!defined($_)) {     # EOF
            print_dir_line;
            exit 0;
        }
        if($blank && /^From /) { # Start of header
            print_dir_line unless (!$msg_nr);
            $msg_nr++;
            ($from,$to,$subj,$date)=("none","none","none", "01-01-80");
            $size=length;
            process_header;
            $blank= 0;
        } else {
            $size += length;
            $blank= /^$/;
        }
    }
}

sub mailfs_copyout {
    my($source,$dest)=@_;
    exit 1 unless (open STDOUT, ">$dest");
    ($nr)= ($source =~ /^(\d+)/); # extract message number from "filename"

    my $blank = 1;
    while(<IN>) {
        if($blank && /^From /) {
            $msg_nr++;
            exit(0) if ($msg_nr > $nr);
            $blank= 0;
        } else {
            $blank= /^$/;
        }
        print if ($msg_nr == $nr);
    }
}

sub mailfs_copyin {
    my($dest,$source)=@_;
    my $now= localtime;
    my $user=get_user_name;

    exit 1 if
      ( $zip                    # don't copy into compressed files
        || (! -f $source)
        || (-B  $source)        # refuse to copy binary files
        || !(open STDOUT, ">$mbox_name.tmp"));

    while (<IN>) {
        print;
    }
    close IN;

    exit 1 unless (open IN, "<$source");
    $_=<IN>;
    # Insert "From " line if necessary:
    $_="From $user\@mailfs.midnight.commander  $now\n"
      unless (/^From /);
    print;

    # Does it look like some valid header?
    if ($_=<IN> !~ /^[A-Z][-a-z0-9_]+: /) {
        $_=  "Date: $now\nFrom: $user\nSubject: $dest\n\n$_";
    }
    print;

    while (<IN>) {
        print ">" if /^From /;
        print;
    }

    close STDOUT; close IN;
    exit 1 unless rename ( "$mbox_name.tmp", $mbox_name);
}

sub mailfs_rm {
    my($source)=@_;
    ($nr)= ($source =~ /^(\d+)/); # extract message number from "filename"

    exit 1 if
      ( $zip                    # don't delete from compressed files
        || (! $nr )
        || !(open STDOUT, ">$mbox_name.tmp"));

    my $blank = 1;
    while(<IN>) {
        if($blank && /^From /) {
            $msg_nr++;
            $blank= 0;
        } else {
            $blank= /^$/;
        }
        print if ($msg_nr != $nr);
    }

    close IN;

    exit 1 unless rename ( "$mbox_name.tmp", $mbox_name);
}

# main {
$msg_nr=0;
$cmd=shift;
$mbox_name=shift;
$_=`$file $mbox_name`;
$zip="";


if (/gzip/) {
    exit 1 unless (open IN, "$zcat $mbox_name|");
    $zip="gzip";
} elsif (/bzip/) {
    $zip="bzip";
    exit 1 unless (open IN, "$bzcat $mbox_name|");
} else {
    exit 1 unless (open IN, "<$mbox_name");
}

umask 077;

if($cmd eq "list") { &mailfs_list; exit 0; }
elsif($cmd eq "copyout") { &mailfs_copyout(@ARGV); exit 0; }
elsif($allow_write and $cmd eq "copyin") { &mailfs_copyin(@ARGV); exit 0; }
elsif($allow_write and $cmd eq "rm") { &mailfs_rm(@ARGV); exit 0; }

exit 1;


Reply via email to