[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 メーリングリストの案内