]> Sergey Matveev's repositories - public-inbox.git/commitdiff
imap: LIST shows "INBOX" in all caps
authorEric Wong <e@yhbt.net>
Wed, 10 Jun 2020 07:05:05 +0000 (07:05 +0000)
committerEric Wong <e@yhbt.net>
Sat, 13 Jun 2020 07:55:45 +0000 (07:55 +0000)
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
lib/PublicInbox/IMAPD.pm
t/imapd.t

index d3f4874e496a99cd20721a7446aca997b8a1d399..b3c449b0712778b571ab2cbbb0d5e24b72e53c65 100644 (file)
@@ -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"));
 }
index 261d756042fbf7ee2856e486d11e28c46b3202e4..186ec7b0062976523bb420eeec3eb768d5ca65aa 100644 (file)
@@ -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) ?
index 233be9f2c0a796b469d99dcd2ddfbe94deb12692..c691e1a96a7026b3228cdcaaa2f1ebd466b22eb7 100644 (file)
--- 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');