]> diplodocus.org Git - minc/blobdiff - minc
(find_mh_folder): Require $regexp to be a regular expression object
[minc] / minc
diff --git a/minc b/minc
index 39ed23055153ccc4f4b35fa448eaab0913f07f0a..cbf2996d453c0e81bb1b3e74bfa69c493a8584e0 100755 (executable)
--- a/minc
+++ b/minc
@@ -12,7 +12,7 @@ B<minc> [B<-m> I<MAX>] [B<-n>]
 
 B<minc> B<-d>
 
-B<minc> B<-h>
+B<minc> B<-r>
 
 =head1 DESCRIPTION
 
@@ -80,6 +80,10 @@ Stop processing after I<MAX> messages.
 Dry run; do not actually incorporate the mail, but log and report to
 stdout/stderr as normal.
 
+=item B<-r>
+
+Rebuild `mhpath +`/.folders from scratch, processing no mail.
+
 =back
 
 =cut
@@ -88,12 +92,14 @@ my $dumpfilters;
 my $help;
 my $maxmsgs;
 my $norun;
+my $rebuild_dot_folders;
 
 GetOptions(
            'd' => \$dumpfilters,
            'h|help' => \$help,
            'm=i' => \$maxmsgs,
            'n' => \$norun,
+           'r' => \$rebuild_dot_folders,
           ) or pod2usage();
 $help and pod2usage(-exitstatus=>0, -verbose=>1);
 @ARGV == 0 or pod2usage();
@@ -152,10 +158,6 @@ by lukem's B<new(1)> (XXX need a link).
 
 Where B<minc> logs what it does, unless in -n mode.
 
-=item `mhpath +`/logs/dryrun.log
-
-Where B<minc> logs what it would do; used in -n mode.
-
 =item `mhpath +`/.minc.context
 
 B<minc> uses this file for context (i.e. current folder) instead of
@@ -176,18 +178,15 @@ our (@start_hooks, @stop_hooks, @filter_hooks, @post_store_hooks);
 our $SCAN_P_FOLDER = 0.1;
 our $SCAN_P_MESSAGE = 0.0625;
 our $SCAN_P_FROM = 0.175;
+our @folder_sort_list = (qr/^inbox$/);
+our $folder_sorter = sub { sort_by_list(@_, @folder_sort_list) };
 
 my $mh;
-my $logfile;
 
 $mh = `mhpath +`;
 chomp($mh);
 
-if ($run) {
-    $logfile = $mh . '/logs/minc.log';
-} else {
-    $logfile = $mh . '/logs/dryrun.log';
-}
+my $logfile = $mh . '/logs/minc.log';
 
 $ENV{"MHCONTEXT"} = $mh . '/.minc.context';
 
@@ -196,6 +195,8 @@ $ENV{"MHCONTEXT"} = $mh . '/.minc.context';
 # Logging
 
 sub mylog {
+    $run or return;
+
     my $timestamp = strftime('%b %e %H:%M:%S', localtime);
     my $msg;
     foreach my $part (@_) {
@@ -239,6 +240,26 @@ sub log_headers {
 ###############################################################################
 # Utility procedures
 
+sub sort_by_list {
+    my $a = shift;
+    my $b = shift;
+
+    for my $i (@_) {
+        my $am = $a =~ $i;
+        my $bm = $b =~ $i;
+        if ($am) {
+            if ($bm) {
+                last;
+            }
+            return -1;
+        } elsif ($bm) {
+            return 1;
+        }
+    }
+
+    return $a cmp $b;
+}
+
 sub mkfolder {
     my $folder = shift;
     my $target;
@@ -467,7 +488,7 @@ sub find_mh_folder {
     my $header;
     my $contents;
     my $pair;
-    my $match;
+    my $regexp;
     my $expression;
     my $result;
 
@@ -487,8 +508,8 @@ sub find_mh_folder {
                 if ($header =~ /$MAGIC_TO_REGEX/i) {
                     foreach $contents (@{$headers{lc($header)}}) {
                         foreach $pair (@filter) {
-                            ($match, $expression) = @$pair;
-                            if ($contents =~ /$match/i) {
+                            ($regexp, $expression) = @$pair;
+                            if ($contents =~ $regexp) {
                                 if (eval "\$result = \"$expression\"") {
                                     return $result;
                                 }
@@ -505,10 +526,10 @@ sub find_mh_folder {
         # Walk the list of message headers matching the filter's
         # specified header.
         foreach $contents (@{$headers{lc($header)}}) {
-            # Walk the filter's list of match/expression pairs.
+            # Walk the filter's list of regexp/expression pairs.
             foreach $pair (@filter) {
-                ($match, $expression) = @$pair;
-                if ($contents =~ /$match/i) {
+                ($regexp, $expression) = @$pair;
+                if ($contents =~ $regexp) {
                     if (eval "\$result = \"$expression\"") {
                         return $result;
                     }
@@ -570,8 +591,11 @@ sub filter_mail {
             $spam++;
         } else {
             $saved++;
-            my $from = [@{$headers{'from'}}]->[-1];
-            my $subject = [@{$headers{'subject'}}]->[-1];
+            my $from = '';
+            my $subject = '';
+            # Sometimes these headers are missing...
+            eval { $from = [@{$headers{'from'}}]->[-1] };
+            eval { $subject = [@{$headers{'subject'}}]->[-1] };
             for ($from, $subject) {
                 tr/\x00-\x1f\x80-\xff/ /;
             }
@@ -602,20 +626,16 @@ sub filter_mail {
     return %folders;
 }
 
-sub update_folders {
+sub build_dot_folders {
     my $folders = shift;
-    my ($fh, $fn);
+    my $fh = shift;
+    my $fn;
 
-    if (open($fh, "$mh/.folders")) {
+    if (defined($fh)) {
         while (<$fh>) {
             chomp;
             $folders->{$_}++;
         }
-    } elsif (not $!{ENOENT}) {
-        # For ENOENT, we go ahead and create it, else we error and
-        # don't clobber it.
-        warn("open($mh/.folders): $!");
-        return;
     }
 
     eval { ($fh, $fn) = tempfile("$mh/.folders.XXXXX") };
@@ -624,9 +644,7 @@ sub update_folders {
         return;
     }
 
-    print($fh "inbox\n");
-    for my $folder (sort(keys(%$folders))) {
-        $folder eq 'inbox' and next;
+    for my $folder (sort { $folder_sorter->($a,$b) } keys(%$folders)) {
         print($fh "$folder\n");
     }
 
@@ -639,6 +657,32 @@ sub update_folders {
     rename($fn, "$mh/.folders") or warn("rename($fn, $mh/.folders): $!");
 }
 
+sub create_dot_folders {
+    if (-f "$HOME/.minc") {
+        require "$HOME/.minc";
+    }
+
+    my %folders;
+    open(my $fh, '-|', 'folders', '-fast', '-recur')
+      or die("open(folders|): $!");
+    build_dot_folders(\%folders, $fh);
+    return 0;
+}
+
+sub update_dot_folders {
+    my $folders = shift;
+    my $fh;
+
+    if (not open($fh, "$mh/.folders") and not $!{ENOENT}) {
+        # For ENOENT, we go ahead and create it, else we error and
+        # don't clobber it.
+        warn("open($mh/.folders): $!");
+        return;
+    }
+
+    build_dot_folders($folders, $fh);
+}
+
 \f
 MAIN: {
     my $st;
@@ -650,6 +694,8 @@ MAIN: {
         exit;
     }
 
+    $rebuild_dot_folders and exit(create_dot_folders);
+
     chdir("$MAILDIR/new") or die("chdir($MAILDIR/new): $!");
     my %folders = filter_mail(map { $_->[1] }
                 sort { $a->[0] <=> $b->[0] }
@@ -661,7 +707,7 @@ MAIN: {
                 }
                 getfiles('.'));
 
-    $run and update_folders(\%folders);
+    $run and update_dot_folders(\%folders);
 
     @SPAM and (exec('scan', '+SPAM', @SPAM) or die);
 }