]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/IMAP.pm
No ext_urls
[public-inbox.git] / lib / PublicInbox / IMAP.pm
index 19ead70c9d7c3968c3e5d4f244446079c869b488..37317948490234f0c9ce2dc75f5bacc4541501ea 100644 (file)
@@ -138,6 +138,7 @@ sub login_success ($$) {
 sub auth_challenge_ok ($) {
        my ($self) = @_;
        my $tag = delete($self->{-login_tag}) or return;
+       $self->{anon} = 1;
        login_success($self, $tag);
 }
 
@@ -350,21 +351,18 @@ sub idle_done ($$) {
        "$idle_tag OK Idle done\r\n";
 }
 
-sub ensure_slices_exist ($$$) {
-       my ($imapd, $ibx, $max) = @_;
-       defined(my $mb_top = $ibx->{newsgroup}) or return;
+sub ensure_slices_exist ($$) {
+       my ($imapd, $ibx) = @_;
+       my $mb_top = $ibx->{newsgroup} // return;
        my $mailboxes = $imapd->{mailboxes};
-       my @created;
-       for (my $i = int($max/UID_SLICE); $i >= 0; --$i) {
+       my $list = $imapd->{mailboxlist}; # may be undef, just autoviv + noop
+       for (my $i = int($ibx->art_max/UID_SLICE); $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;
+               push @$list, qq[* LIST (\\HasNoChildren) "." $sub_mailbox\r\n]
        }
-       return unless @created;
-       my $l = $imapd->{mailboxlist} or return;
-       push @$l, map { qq[* LIST (\\HasNoChildren) "." $_\r\n] } @created;
 }
 
 sub inbox_lookup ($$;$) {
@@ -387,7 +385,8 @@ sub inbox_lookup ($$;$) {
                        my $uid_end = $uid_base + UID_SLICE;
                        $exists = $over->imap_exists($uid_base, $uid_end);
                }
-               ensure_slices_exist($self->{imapd}, $ibx, $over->max);
+               delete $ibx->{-art_max};
+               ensure_slices_exist($self->{imapd}, $ibx);
        } else {
                if ($examine) {
                        $self->{uid_base} = $uid_base;
@@ -396,9 +395,9 @@ sub inbox_lookup ($$;$) {
                }
                # if "INBOX.foo.bar" is selected and "INBOX.foo.bar.0",
                # check for new UID ranges (e.g. "INBOX.foo.bar.1")
-               if (my $z = $self->{imapd}->{mailboxes}->{"$mailbox.0"}) {
-                       ensure_slices_exist($self->{imapd}, $z,
-                                               $z->over(1)->max);
+               if (my $ibx = $self->{imapd}->{mailboxes}->{"$mailbox.0"}) {
+                       delete $ibx->{-art_max};
+                       ensure_slices_exist($self->{imapd}, $ibx);
                }
        }
        ($ibx, $exists, $uidmax + 1, $uid_base);
@@ -427,8 +426,10 @@ sub _esc ($) {
        if (!defined($v)) {
                'NIL';
        } elsif ($v =~ /[{"\r\n%*\\\[]/) { # literal string
+               utf8::encode($v);
                '{' . length($v) . "}\r\n" . $v;
        } else { # quoted string
+               utf8::encode($v);
                qq{"$v"}
        }
 }
@@ -576,6 +577,16 @@ sub fetch_run_ops {
        $self->msg_more(")\r\n");
 }
 
+sub requeue { # overrides PublicInbox::DS::requeue
+       my ($self) = @_;
+       if ($self->{anon}) { # AUTH=ANONYMOUS gets high priority
+               $self->SUPER::requeue;
+       } else { # low priority
+               push(@{$self->{imapd}->{-authed_q}}, $self) == 1 and
+                       PublicInbox::DS::requeue($self->{imapd});
+       }
+}
+
 sub fetch_blob_cb { # called by git->cat_async via ibx_async_cat
        my ($bref, $oid, $type, $size, $fetch_arg) = @_;
        my ($self, undef, $msgs, $range_info, $ops, $partial) = @$fetch_arg;
@@ -590,10 +601,9 @@ sub fetch_blob_cb { # called by git->cat_async via ibx_async_cat
                $smsg->{blob} eq $oid or die "BUG: $smsg->{blob} != $oid";
        }
        my $pre;
-       if (!$self->{wbuf} && (my $nxt = $msgs->[0])) {
-               $pre = ibx_async_prefetch($ibx, $nxt->{blob},
+       ($self->{anon} && !$self->{wbuf} && $msgs->[0]) and
+               $pre = ibx_async_prefetch($ibx, $msgs->[0]->{blob},
                                        \&fetch_blob_cb, $fetch_arg);
-       }
        fetch_run_ops($self, $smsg, $bref, $ops, $partial);
        $pre ? $self->dflush : $self->requeue_once;
 }
@@ -997,7 +1007,7 @@ sub fetch_compile ($) {
        # stabilize partial order for consistency and ease-of-debugging:
        if (scalar keys %partial) {
                $need |= NEED_BLOB;
-               $r[2] = [ map { [ $_, @{$partial{$_}} ] } sort keys %partial ];
+               @{$r[2]} = map { [ $_, @{$partial{$_}} ] } sort keys %partial;
        }
 
        push @op, $OP_EML_NEW if ($need & (EML_HDR|EML_BDY));
@@ -1020,7 +1030,7 @@ sub fetch_compile ($) {
 
        # r[1] = [ $key1, $cb1, $key2, $cb2, ... ]
        use sort 'stable'; # makes output more consistent
-       $r[1] = [ map { ($_->[2], $_->[1]) } sort { $a->[0] <=> $b->[0] } @op ];
+       @{$r[1]} = map { ($_->[2], $_->[1]) } sort { $a->[0] <=> $b->[0] } @op;
        @r;
 }
 
@@ -1157,17 +1167,11 @@ sub process_line ($$) {
        my $err = $@;
        if ($err && $self->{sock}) {
                $l =~ s/\r?\n//s;
-               err($self, 'error from: %s (%s)', $l, $err);
+               warn("error from: $l ($err)\n");
                $tag //= '*';
-               $res = "$tag BAD program fault - command not performed\r\n";
+               $res = \"$tag BAD program fault - command not performed\r\n";
        }
-       return 0 unless defined $res;
-       $self->write($res);
-}
-
-sub err ($$;@) {
-       my ($self, $fmt, @args) = @_;
-       printf { $self->{imapd}->{err} } $fmt."\n", @args;
+       defined($res) ? $self->write($res) : 0;
 }
 
 sub out ($$;@) {
@@ -1178,7 +1182,7 @@ sub out ($$;@) {
 # callback used by PublicInbox::DS for any (e)poll (in/out/hup/err)
 sub event_step {
        my ($self) = @_;
-
+       local $SIG{__WARN__} = $self->{imapd}->{warn_cb};
        return unless $self->flush_write && $self->{sock} && !$self->{long_cb};
 
        # only read more requests if we've drained the write buffer,