[Mew-dist 1603] Re: qmail patch of LocalMbox.pm

Motonori Nakamura motonori at example.com
1997年 8月 24日 (日) 15:37:32 JST


>>>>> On Sun, 24 Aug 1997 13:04:51 +0900, Kazu Yamamoto (山本和彦) <Kazu at example.com> said:

> ただ、一つだけ、変更して欲しいところがあります。

2つのループのうち、前半はディレクトリチェック、後半はファイルチェック
といことにしました。

Kazu> 混乱して来ましたので、im-63.tar.gz にまとめました。

というわけで、im-63 へのパッチです。

若宮さんの imap パッチもマージしました。
UID を使ってないところも使うようにしたのと、
imls %folder last:3 のように書くこともできるようにしました。

# imls のときに、本文の先頭が見られないのが残念ですね。

他にも、imget でもメッセージサイズを記録するようにしたなどの
修正があります。

- motonori


-------------- next part --------------
diff -ur ../im-63-/IM.in/Config.pm.in ./IM.in/Config.pm.in
--- ../im-63-/IM.in/Config.pm.in	Sun Aug 24 12:12:38 1997
+++ ./IM.in/Config.pm.in	Sun Aug 24 14:54:06 1997
@@ -406,7 +406,7 @@
 		splice(@$argref, $ref, 1);
 	    }
 	    set_value($desc, $vnam, $val, 'opt');
-	} elsif (/^[+=.\/~]/ && $O_FOPT) {
+	} elsif (/^[+\-=%.\/~]/ && $O_FOPT) {
 	    $name = $O_FOPT;
 	    $val = $_;
 	    $desc = $O_DESC{$name} || im_die("unknown option $name\n"); # must be F or F@
@@ -549,7 +549,7 @@
 	if ($desc =~ /F/) { # xxx how about f
 	    my ($i, $N) = (0, scalar(@val));
 	    while ($i < $N) {
-		$val[$i] = "+$val[$i]" unless $val =~ /^[+-=%~]/;
+		$val[$i] = "+$val[$i]" unless $val =~ /^[+\-=%~]/;
 		$i++;
 	    }
 	}
@@ -578,7 +578,7 @@
 	    }
 	} elsif ($desc =~ /F/) {  # xxx how about f
 	    # +inbox -> + inbox -> --src +inbox
-	    if ($val =~ /^[+-=%~]/) {
+	    if ($val =~ /^[+\-=%~]/) {
 		${$vnam} = $val;
 	    } else {
 		${$vnam} = "+$val";
@@ -608,7 +608,7 @@
 	}
     } elsif ($desc =~ /F/) {  # xxx how about f
 	# +inbox -> + inbox -> --src +inbox
-	if ($val =~ /^[+-=%]/) {
+	if ($val =~ /^[+\-=%]/) {
 	    $case->{$vnam} = $val;
 	} else {
 	    $case->{$vnam} = "+$val";
diff -ur ../im-63-/IM.in/Imap.pm.in ./IM.in/Imap.pm.in
--- ../im-63-/IM.in/Imap.pm.in	Sun Aug 17 14:50:06 1997
+++ ./IM.in/Imap.pm.in	Sun Aug 24 15:27:35 1997
@@ -23,13 +23,14 @@
 use IM::TcpTransaction;
 use IM::GetPass;
 use IM::MsgStore;
+use IM::Scan;
 
 @ISA = qw(Exporter);
 @EXPORT = qw(
     imap_open imap_close imap_select imap_head imap_from imap_get imap_put
     imap_delete imap_copy imap_flags
     imap_list_folder imap_create_folder imap_delete_folder imap_rename_folder
-    imap_get_msg imap_process imap_spec
+    imap_get_msg imap_process imap_spec imap_scan_folder
 );
 
 =head1 NAME
@@ -190,9 +191,9 @@
     my ($seq) = $ImapSeq++;
     local (@message);
     im_notice("getting message $num.\n");
-    my $resp = &send_command(\*IMAPd, "im$seq FETCH $num RFC822", '');
+    my $resp = &send_command(\*IMAPd, "im$seq UID FETCH $num RFC822", '');
     my $failed = 0;
-    if ($resp =~ /^\* $num FETCH \(RFC822 \{(\d+)\}/i) {
+    if ($resp =~ /^\* $num FETCH \(UID \d+ RFC822 \{(\d+)\}/i) {
 	my $size = $1;
 	while (<IMAPd>) {
 	    $size -= length($_);
@@ -218,12 +219,12 @@
     my ($seq) = $ImapSeq++;
     im_notice("getting header of message $num.\n");
     my $resp = &send_command(\*IMAPd,
-      "im$seq FETCH $num (RFC822.SIZE RFC822.HEADER)", '');
+      "im$seq UID FETCH $num (RFC822.SIZE RFC822.HEADER)", '');
     my $failed = 0;
     local (%head);
     undef %head;
-    if ($resp =~ /^\* $num FETCH \(RFC822.SIZE (\d+) RFC822.HEADER \{(\d+)\}/i)
-    {
+    if ($resp =~
+      /^\* $num FETCH \(UID \d+ RFC822.SIZE (\d+) RFC822.HEADER \{(\d+)\}/i) {
 	my ($size, $len) = ($1, $2);
 	my $field = '';
 	while (<IMAPd>) {
@@ -266,10 +267,10 @@
     my $failed = 0;
     im_notice("getting sender information of message $num.\n");
 #   my $resp = &send_command(\*IMAPd,
-#     "im$seq FETCH $num RFC822.HEADER.LINES (From Date Subject)", '');
+#     "im$seq UID FETCH $num RFC822.HEADER.LINES (From Date Subject)", '');
     my $resp = &send_command(\*IMAPd,
-      "im$seq FETCH $num RFC822.HEADER.LINES (From)", '');
-    if ($resp =~ /^\* $num FETCH \(RFC822.* \{(\d+)\}/i) {
+      "im$seq UID FETCH $num RFC822.HEADER.LINES (From)", '');
+    if ($resp =~ /^\* $num FETCH \(UID \d+ RFC822.* \{(\d+)\}/i) {
 	my $size = $1;
 	my $found = 0;
 	my $f;
@@ -308,11 +309,12 @@
     my ($flags);
     im_notice("getting flags for $num.\n");
     my $failed = 0;
-    my $resp = &send_command(\*IMAPd, "im$seq FETCH $num FLAGS", '');
+    my $resp = &send_command(\*IMAPd, "im$seq UID FETCH $num FLAGS", '');
     while ($resp !~ /^im$seq/) {
 	if ($resp =~ /^\* NO/i) {
 	    $failed = 1;
-	} elsif ($resp =~ /^\*\s+$num\s+FETCH\s+\(FLAGS\s+\((.*)\)\)/i) {
+	} elsif ($resp =~
+	  /^\*\s+$num\s+FETCH\s+\(UID \d+ FLAGS\s+\((.*)\)\)/i) {
 	    $flags = $1;
 	}
 	$resp = &next_response(\*IMAPd);
@@ -327,7 +329,8 @@
     my $seq = $ImapSeq++;
     my $failed = 0;
     im_notice("deleting message $num.\n");
-    $resp = &send_command(\*IMAPd, "im$seq STORE $num +FLAGS (\\Deleted)", '');
+    $resp = &send_command(\*IMAPd, "im$seq UID STORE $num +FLAGS (\\Deleted)",
+	'');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
 	$resp = &next_response(\*IMAPd);
@@ -415,7 +418,7 @@
     }
     my $seq = $ImapSeq++;
     my $failed = 0;
-    $resp = &send_command(\*IMAPd, "im$seq COPY $srcmsg $dstfolder", '');
+    $resp = &send_command(\*IMAPd, "im$seq UID COPY $srcmsg $dstfolder", '');
     while ($resp !~ /^im$seq/) {
 	$failed = 1 if ($resp =~ /^\* NO/i);
 	$resp = &next_response(\*IMAPd);
@@ -577,6 +580,117 @@
     }
 
     return ($folder, $auth, $user, $host);
+}
+
+############################################
+##
+## For imls
+##
+
+sub imap_scan_folder (@) {
+    my @ranges = @_;
+    my $uid, $size, $len;
+
+    my $msgset = &imap_range2set(@ranges);
+    return -1 if ($msgset < 0);
+    my $seq = $ImapSeq++;
+    my $resp = &send_command(\*IMAPd,
+	"im$seq UID FETCH $msgset (UID RFC822.SIZE RFC822.HEADER)", '');
+    while ($resp =~
+    /^\* \d+ FETCH \(UID (\d+) RFC822.SIZE (\d+) RFC822\.HEADER \{(\d+)\}/i) {
+	($uid, $size, $len) = ($1, $2, $3);
+	my @hdr;
+	while (<IMAPd>) {
+	    $len -= length;
+	    s/\r?\n$/\n/;
+	    im_warn("$_") if (&debug("imap"));
+	    push(@hdr, $_);
+	}
+	$resp = &next_response(\*IMAPd);
+	return -1 if ($resp !~ /^\)/);
+
+	my %Head;
+	&store_header(\%Head, join('', @hdr));
+#	$Head{'bytes:'} = $size;
+	$Head{'kbytes:'} = int(($size + 1023) / 1024);
+	$Head{'number'} = $uid;
+	$Head{'folder'} = "\%$folder";
+	parse_header(\%Head);
+
+	if ($main::opt_thread) {
+	    &make_thread(%Head);
+	} else {
+	    &disp_msg(\%Head);
+	    $main::scan_count++;
+	}
+	$resp = &next_response(\*IMAPd);
+    }
+    if ($resp !~ /^im$seq OK/) {
+	im_warn("FETCH command failed.\n") if (&debug("imap") || &verbose);
+	return -1;
+    }
+    return 0;
+}
+
+sub imap_range2set (@) {
+    my @ranges = @_;
+    my (@uids, $fromuid, $touid, $dir);
+
+    my @alluids = &imap_all_uids();
+    return -1 if ($alluids[0] < 0);
+    my ($min, $max) = ($alluids[0], $alluids[$#alluids]);
+
+    @ranges = ('first-last') if ($#ranges < 0 || grep(/^all$/, @ranges));
+    local $_;
+    foreach (@ranges) {
+	if (/^(\d+|first|last)-(\d+|first|last)$/) {
+	    $fromuid = &imap_message_number($min, $max, $1);
+	    $touid   = &imap_message_number($min, $max, $2);
+	    $_ = "$fromuid:$touid";
+	} elsif (/^(\d+|last|first):([+-]?)(\d+)$/) {
+	    if ($1 eq 'last') {
+		$dir = ($2 eq '+') ? +1 : -1;
+	    } else {
+		$dir = ($2 eq '-') ? -1 : +1;
+	    }
+	    $fromuid = &imap_message_number($min, $max, $1);
+	    if ($dir > 0) {
+		@uids = grep($_ >= $fromuid, @alluids);
+		splice(@uids, $3) if ($3 < @uids);
+	    } else {
+		@uids = grep($_ <= $fromuid, @alluids);
+		splice(@uids, 0, @uids - $3) if ($3 < @uids);
+	    }
+	    $_ = join(',', @uids);
+	} elsif (/^(\d+|first|last)$/) {
+	    $_ = &imap_message_number($min, $max, $1);
+	}
+    }
+    return join(',', @ranges);
+}
+
+sub imap_all_uids () {
+    my ($seq, $resp, @uids);
+
+    $seq = $ImapSeq++;
+    $resp = &send_command(\*IMAPd, "im$seq UID SEARCH 1:*", '');
+    if ($resp =~ /^\* SEARCH (\d+( +\d+)*)/i) {
+	@uids = split(' ', $1);
+    } else {
+	im_warn("SEARCH command failed.\n");
+    }
+    $resp = &next_response(\*IMAPd);
+    return (-1) if ($resp !~ /^im$seq OK/);
+    return @uids;
+}
+
+sub imap_message_number ($$$) {
+    my ($min, $max, $num) = @_;
+
+    return $num if $num =~ /^\d+$/;
+    return $min if $num =~ /^first$/;
+    return $max if $num =~ /^last$/;
+    return '';
 }
 
 1;
diff -ur ../im-63-/IM.in/LocalMbox.pm.in ./IM.in/LocalMbox.pm.in
--- ../im-63-/IM.in/LocalMbox.pm.in	Sun Aug 24 12:56:35 1997
+++ ./IM.in/LocalMbox.pm.in	Sun Aug 24 14:21:05 1997
@@ -76,16 +76,20 @@
 #   my $user = $ENV{'USER'};
 #   $user = $ENV{'LOGNAME'} unless ($user);
     my $user = getlogin;
-    $user = (getpwuid($<))[0] unless ($user);
+    my $home = $ENV{'HOME'};
+    if ($user eq '' || $home eq '') {
+	my @pw = getpwuid($<);
+	$user = $pw[0] unless ($user);
+	$home = $pw[7] unless ($home);
+    }
 
     # set default
     unless ($mbox) {
 	if ($qmail_ok) {
-	    $home = (getpwuid($<))[7] unless ($home);
 	    push(@MailDrops, $ENV{'MAILDIR'}) if ($ENV{'MAILDIR'});
 	    push(@MailDrops, $ENV{'MAILDROP'}) if ($ENV{'MAILDROP'});
 	    push(@MailDrops, $ENV{'MAIL'}) if ($ENV{'MAIL'});
-	    push(@MailDrops, "$home/Maildir", "$home/Mailbox");
+	    push(@MailDrops, "$home/Maildir");
 	    foreach $p (@MailDrops) {
 		if (( -d $p && -d "$p/new" ) || -f $p ) {
 		    $mbox = $p;
@@ -95,14 +99,15 @@
 	}
 	unless ($mbox) {
 	    @MailDrops = (
-		"/var/mail",
-		"/var/spool/mail",
-		"/usr/mail",
-		"/usr/spool/mail"
+		"/var/mail/$user",
+		"/var/spool/mail/$user",
+		"/usr/mail/$user",
+		"/usr/spool/mail/$user"
 	    );
+	    unshift(@MailDrops, "$home/Mailbox") if ($qmail_ok);
 	    foreach $p (@MailDrops) {
-		if ( -f "$p/$user" ) {
-		    $mbox = "$p/$user";
+		if ( -f $p ) {
+		    $mbox = $p;
 		    last;
 		}
 	    }
diff -ur ../im-63-/IM.in/MsgStore.pm.in ./IM.in/MsgStore.pm.in
--- ../im-63-/IM.in/MsgStore.pm.in	Wed Aug 20 19:38:59 1997
+++ ./IM.in/MsgStore.pm.in	Sun Aug 24 15:31:06 1997
@@ -96,12 +96,14 @@
 	$PrevDst = $dst;
     }
     my $file = &new_message(\*ART, $dst);
+    my $size = 0;
     if ($file ne '') {
 	my $line;
 	my $hcount = 0;
 	my $inheader = 1;
 	im_notice("creating $file\n");
 	foreach $line (@$Msg) {
+	    $size += length($line);
 	    if ($line eq "\n") {
 		$inheader = 0;
 	    }
@@ -131,10 +133,17 @@
 	    splice(@$Msg, 0, $hcount);
 	    $Head{'body:'} = &parse_body($Msg, 1);
 
+#	    $Head{'bytes:'} = $size;
+	    $Head{'kbytes:'} = int(($size + 1023) / 1024);
 	    ($Head{'number'} = $file) =~ s/^.*\///;
 	    $Head{'folder'} = $dst;
 	    &parse_header(\%Head);
-	    &disp_msg(\%Head);
+#	    if ($main::opt_thread) {
+#		&make_thread(%Head);
+#	    } else {
+		&disp_msg(\%Head);
+		$main::scan_count++;
+#	    }
 	}
 
 	my $mid = &header_value(\@Hdr, 'Message-ID');
diff -ur ../im-63-/imget.in ./imget.in
--- ../im-63-/imget.in	Sat Aug 23 04:30:42 1997
+++ ./imget.in	Sun Aug 24 15:30:40 1997
@@ -51,6 +51,8 @@
     'form;s;;'	       => 'Scan format',
     'jissafe;b;;'      => 'Safe manner for JIS',
     'width;i;;'        => 'Width of result for scan listings.',
+#   'thread;b;;'       => 'Make threads',
+#   'indent;i;;'       => "Width of thread indent",
     'lock;s;flock;'    => 'Local mailbox locking style. (none,flock,file)',
     'keep;i;0;'        => "Preserve messages.\n" .
 	"\t\t(POP: in days; 0=delete immediately, -1=preserve forever)\n" .
diff -ur ../im-63-/imhist.in ./imhist.in
--- ../im-63-/imhist.in	Fri Aug 15 11:46:48 1997
+++ ./imhist.in	Sun Aug 24 14:21:05 1997
@@ -42,10 +42,10 @@
 
 @OptConfig = (
     'lookup;s;;'      => 'Look up an entry for specified message-id.',
-    'remove;s;;'      => 'Delete an entry for specified message-id.',
+    'remove;s;;'      => 'Remove whole information on specified message-id.',
     'msg;s;;'         => 'Message to be deleted if multiple in database.',
     'dump;b;;'        => 'Dump database just for debugging.',
-    'add;f;;'         => 'Add information of messages into database.',
+    'add;f;;'         => 'Add information of messages in a specified folder.',
     'subfolders;b;;'  => 'Descend sub folders recursively (option for --add).',
     'help;b;;'        => "Show this message.",
     );
@@ -67,7 +67,11 @@
     im_die("MsgDBFile is not defined.\n");
 }
 if ($opt_lookup ne '') {
-    exit $EXIT_ERROR if (open_history(0) < 0);
+    exit $EXIT_ERROR if (open_history(1) < 0);
+    unless ($opt_lookup =~ /^<.*>$/) {
+	im_warn("Message-ID should be surrounded by <>.\n");
+	exit $EXIT_ERROR;
+    }
     my $msg = lookup_history($opt_lookup, LookUpMsg);
     if ($msg eq '') {
 	im_info("no entry found for $opt_lookup\n");
@@ -78,6 +82,10 @@
     close_history();
 } elsif ($opt_delete ne '') {
     exit $EXIT_ERROR if (open_history(1) < 0);
+    unless ($opt_lookup =~ /^<.*>$/) {
+	im_warn("Message-ID should be surrounded by <>.\n");
+	exit $EXIT_ERROR;
+    }
     my $num = delete_history($opt_delete, $opt_msg);
     if ($num < 0) {
 	im_warn("no entry found for $opt_delete\n");
diff -ur ../im-63-/imls.in ./imls.in
--- ../im-63-/imls.in	Fri Aug 15 17:02:08 1997
+++ ./imls.in	Sun Aug 24 14:59:29 1997
@@ -27,7 +27,6 @@
 use IM::Stdio;
 
 #&set_debug("all", 1);
-#&set_verbose(1);
 
 ##
 ## Environments
@@ -98,11 +97,11 @@
 	&local_files($_, @ARGV);
     } elsif (/^-(.*)$/) {
 	require IM::Nntp && import IM::Nntp;
-	&nntp_messages($1);
-    } elsif (/^\%(.*)$/) {
+	&nntp_messages($1, @ARGV);
+    } elsif (/^(\%.*)$/) {
 	require IM::Imap && import IM::Imap;
 	require IM::GetPass && import IM::GetPass;
-	&imap_messages($1);
+	&imap_messages($1, @ARGV);
     } else {
 	im_die("doesn't support $opt_src\n");
     }
@@ -152,8 +151,8 @@
 ## News by NNTP
 ##
 
-sub nntp_messages ($) {
-    my $newsgroup = shift;
+sub nntp_messages ($@) {
+    my ($newsgroup, @ranges) = @_;
     my ($resp, $start, $end);
 #   my ($num, $subj, $from, $date, $id, $ref, $num1, $num2);
 
@@ -194,13 +193,12 @@
 #   if ($start < $FIRST) { $start = $FIRST; }
 #   if ($LAST < $end)    { $end = $LAST; }
 
-    if ($ARGV[0] ne 'all') {
-	@ranges = get_nntp_message_range($start, $end, @ARGV);
+    if ($ranges[0] ne 'all') {
+	@ranges = get_nntp_message_range($start, $end, @ranges);
 	($start, $end) = ($ranges[0], $ranges[$#ranges]);
 #	printf "%s -> %s\n", $ARGV[0], join(',', @ranges);
     }
 
-
     if (&nntp_command("XOVER $start-$end", '')) {
 	im_err("XOVER command failed.\n");
 	im_warn("trying HEAD command.\n");
@@ -429,8 +427,8 @@
 ## IMAP
 ##
 
-sub imap_messages ($) {
-    my $folder = shift;
+sub imap_messages ($@) {
+    my ($folder, @ranges) = @_;
     my ($host, $user, $auth);
 
     if ($folder !~ /[:\@]/) {
@@ -447,38 +445,26 @@
 	im_warn("$ErrMsg\n");
 #	im_warn("IMAP connection was not established.\n")
 #	  if (&debug("imap") || &verbose);
+	$scan_count = -1;
 	return -1;
     }
-    my $start = 1;
-    my $end = &imap_select($folder, 1);
-    if ($msgs < 0) {
-	&imap_close;
-	im_warn("can't access to $folder");
-	return -1;
-    } elsif ($msgs < $msg) {
+    my $exists = &imap_select($folder, 1);
+    if ($exists < 0) {
 	&imap_close;
-	im_info("message $msg not found in \%$folder");
+	im_warn("can't select $folder\@$host.\n");
+	$scan_count = -1;
 	return -1;
     }
-
-#   if ($ARGV[0] ne 'all') {
-#	# XXX
-#   }
-
-    foreach $i ($start..$end) {
-	(my $rc, local *Head) = &imap_head($i);
-	next if ($rc < 0);
-	$Head{'number'} = $i;
-	$Head{'folder'} = "\%$folder";
-	parse_header(\%Head);
-	if ($opt_thread) {
-	    &make_thread(%Head);
-	} else {
-	    &disp_msg(\%Head);
-	    $scan_count++;
+    if ($exists > 0) {
+	if (&imap_scan_folder(@ranges) < 0) {
+	    &imap_close;
+	    im_warn("IMAP folder scanning error.\n");
+	    $scan_count = -1;
+	    return -1;
 	}
     }
     &imap_close;
+    return 0;
 }
 
 sub sort_uniq (@) {


Mew-dist メーリングリストの案内