IMAP RFC 3501 stipulates case-insensitive comparisons, and so
does RFC 977 (NNTP). However, INN (nnrpd) uses case-sensitive
comparisons, so we've always used case-sensitive comparisons for
NNTP to match nnrpd behavior.
Unfortunately, some IMAP clients insist on sending "INBOX" with
caps, which causes problems for us. Since NNTP group names are
typically all lowercase anyways, just force all comparisons to
lowercase for IMAP and warn admins if uppercase-containing
newsgroups won't be accessible over IMAP.
This ensures our existing -nntpd behavior remains unchanged
while being compatible with the expectations of real-world IMAP
clients.
my ($self) = @_;
my @names = map { $_->{newsgroup} } @{delete $self->{grouplist}};
my %ns; # "\Noselect \HasChildren"
my ($self) = @_;
my @names = map { $_->{newsgroup} } @{delete $self->{grouplist}};
my %ns; # "\Noselect \HasChildren"
+
+ if (my @uc = grep(/[A-Z]/, @names)) {
+ warn "Uppercase not allowed for IMAP newsgroup(s):\n",
+ map { "\t$_\n" } @uc;
+ my %uc = map { $_ => 1 } @uc;
+ @names = grep { !$uc{$_} } @names;
+ }
for (@names) {
my $up = $_;
while ($up =~ s/\.[^\.]+\z//) {
for (@names) {
my $up = $_;
while ($up =~ s/\.[^\.]+\z//) {
use PublicInbox::IMAPD;
{ # make sure we get '%' globbing right
use PublicInbox::IMAPD;
{ # make sure we get '%' globbing right
- my @n = map { { newsgroup => $_ } } (qw(x.y.z x.z.y));
+ my @w;
+ local $SIG{__WARN__} = sub { push @w, @_ };
+ my @n = map { { newsgroup => $_ } } (qw(x.y.z x.z.y IGNORE.THIS));
my $self = { imapd => { grouplist => \@n } };
PublicInbox::IMAPD::refresh_inboxlist($self->{imapd});
my $self = { imapd => { grouplist => \@n } };
PublicInbox::IMAPD::refresh_inboxlist($self->{imapd});
+ is(scalar(@w), 1, 'got a warning for upper-case');
+ like($w[0], qr/IGNORE\.THIS/, 'warned about upper-case');
+
my $res = PublicInbox::IMAP::cmd_list($self, 'tag', 'x', '%');
is(scalar($$res =~ tr/\n/\n/), 2, 'only one result');
like($$res, qr/ x\r\ntag OK/, 'saw expected');
my $res = PublicInbox::IMAP::cmd_list($self, 'tag', 'x', '%');
is(scalar($$res =~ tr/\n/\n/), 2, 'only one result');
like($$res, qr/ x\r\ntag OK/, 'saw expected');
ok(!$mic->select('foo') && ($e = $@), 'EXAMINE non-existent');
like($e, qr/\bNO\b/, 'got a NO on EXAMINE for non-existent');
ok($mic->select('inbox.i1'), 'SELECT succeeds');
ok(!$mic->select('foo') && ($e = $@), 'EXAMINE non-existent');
like($e, qr/\bNO\b/, 'got a NO on EXAMINE for non-existent');
ok($mic->select('inbox.i1'), 'SELECT succeeds');
-ok($mic->examine('inbox.i1'), 'EXAMINE succeeds');
+ok($mic->examine('INBOX.i1'), 'EXAMINE succeeds');
my @raw = $mic->status('inbox.i1', qw(Messages uidnext uidvalidity));
is(scalar(@raw), 2, 'got status response');
like($raw[0], qr/\A\*\x20STATUS\x20inbox\.i1\x20
my @raw = $mic->status('inbox.i1', qw(Messages uidnext uidvalidity));
is(scalar(@raw), 2, 'got status response');
like($raw[0], qr/\A\*\x20STATUS\x20inbox\.i1\x20