From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 1C3511FC00 for ; Wed, 10 Jun 2020 07:07:32 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 68/82] imap: LIST shows "INBOX" in all caps Date: Wed, 10 Jun 2020 07:05:05 +0000 Message-Id: <20200610070519.18252-69-e@yhbt.net> In-Reply-To: <20200610070519.18252-1-e@yhbt.net> References: <20200610070519.18252-1-e@yhbt.net> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: While selecting a mailbox is done case-insensitively, "INBOX" is special for the LIST command, according to RFC 3501 6.3.8: > The special name INBOX is included in the output from LIST, if > INBOX is supported by this server for this user and if the > uppercase string "INBOX" matches the interpreted reference and > mailbox name arguments with wildcards as described above. The > criteria for omitting INBOX is whether SELECT INBOX will > return failure; it is not relevant whether the user's real > INBOX resides on this or some other server. Thus, the existing news.public-inbox.org convention of naming newsgroups starting with "inbox." needs to be special-cased to not confuse clients. While we're at it, do not create ".0" for dummy newsgroups if they're selected, either. --- lib/PublicInbox/IMAP.pm | 8 ++++---- lib/PublicInbox/IMAPD.pm | 4 +++- t/imapd.t | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm index d3f4874e496..b3c449b0712 100644 --- a/lib/PublicInbox/IMAP.pm +++ b/lib/PublicInbox/IMAP.pm @@ -254,13 +254,14 @@ sub cmd_done ($$) { sub ensure_ranges_exist ($$$) { my ($imapd, $ibx, $max) = @_; + defined(my $mb_top = $ibx->{newsgroup}) or return; my $mailboxes = $imapd->{mailboxes}; - my $mb_top = $ibx->{newsgroup}; my @created; for (my $i = int($max/UID_BLOCK); $i >= 0; --$i) { my $sub_mailbox = "$mb_top.$i"; last if exists $mailboxes->{$sub_mailbox}; $mailboxes->{$sub_mailbox} = $ibx; + $sub_mailbox =~ s/\Ainbox\./INBOX./i; # more familiar to users push @created, $sub_mailbox; } return unless @created; @@ -693,9 +694,8 @@ sub cmd_list ($$$$) { # request for hierarchy delimiter $l = [ qq[* LIST (\\Noselect) "." ""\r\n] ]; } elsif ($refname ne '' || $wildcard ne '*') { - $wildcard = lc $wildcard; - $wildcard =~ s!([^a-z0-9_])!$patmap{$1} // "\Q$1"!eg; - $l = [ grep(/ \Q$refname\E$wildcard\r\n\z/s, @$l) ]; + $wildcard =~ s!([^a-z0-9_])!$patmap{$1} // "\Q$1"!egi; + $l = [ grep(/ \Q$refname\E$wildcard\r\n\z/is, @$l) ]; } \(join('', @$l, "$tag OK List done\r\n")); } diff --git a/lib/PublicInbox/IMAPD.pm b/lib/PublicInbox/IMAPD.pm index 261d756042f..186ec7b0062 100644 --- a/lib/PublicInbox/IMAPD.pm +++ b/lib/PublicInbox/IMAPD.pm @@ -71,7 +71,9 @@ sub imapd_refresh_finalize { $imapd->{inboxlist} = [ map { my $no = $mailboxes->{$_} == $dummy ? '' : 'No'; - qq[* LIST (\\Has${no}Children) "." $_\r\n] + my $u = $_; # capitalize "INBOX" for user-familiarity + $u =~ s/\Ainbox(\.|\z)/INBOX$1/i; + qq[* LIST (\\Has${no}Children) "." $u\r\n] } sort { # shortest names first, alphabetically if lengths match length($a) == length($b) ? diff --git a/t/imapd.t b/t/imapd.t index 233be9f2c0a..c691e1a96a7 100644 --- a/t/imapd.t +++ b/t/imapd.t @@ -101,13 +101,13 @@ like($raw[0], qr/\A\*\x20STATUS\x20inbox\.i1\.$first_range\x20 like($raw[1], qr/\A\S+ OK /, 'finished status response'); my @orig_list = @raw = $mic->list; -like($raw[0], qr/^\* LIST \(.*?\) "\." inbox/, +like($raw[0], qr/^\* LIST \(.*?\) "\." INBOX/, 'got an inbox'); like($raw[-1], qr/^\S+ OK /, 'response ended with OK'); is(scalar(@raw), scalar(@V) + 4, 'default LIST response'); @raw = $mic->list('', 'inbox.i1'); is(scalar(@raw), 2, 'limited LIST response'); -like($raw[0], qr/^\* LIST \(.*?\) "\." inbox/, +like($raw[0], qr/^\* LIST \(.*?\) "\." INBOX/, 'got an inbox.i1'); like($raw[-1], qr/^\S+ OK /, 'response ended with OK');