X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FIMAP.pm;h=37317948490234f0c9ce2dc75f5bacc4541501ea;hb=5198c976ce8b1954f0f76a0da152cc434411f147;hp=805f1102536d99d9cf77807f86e1b0b3e6290ce4;hpb=23af251dd607c4e75ab1e68063f2c885c48cc035;p=public-inbox.git diff --git a/lib/PublicInbox/IMAP.pm b/lib/PublicInbox/IMAP.pm index 805f1102..37317948 100644 --- a/lib/PublicInbox/IMAP.pm +++ b/lib/PublicInbox/IMAP.pm @@ -121,7 +121,7 @@ sub capa ($) { $capa .= ' COMPRESS=DEFLATE'; } else { if (!($self->{sock} // $self)->can('accept_SSL') && - $self->{imapd}->{accept_tls}) { + $self->{imapd}->{ssl_ctx_opt}) { $capa .= ' STARTTLS'; } $capa .= ' AUTH=ANONYMOUS'; @@ -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,12 +601,11 @@ 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->zflush : $self->requeue_once; + $pre ? $self->dflush : $self->requeue_once; } sub emit_rfc822 { @@ -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, @@ -1230,14 +1234,12 @@ sub cmd_compress ($$$) { sub cmd_starttls ($$) { my ($self, $tag) = @_; - my $sock = $self->{sock} or return; - if ($sock->can('stop_SSL') || $self->compressed) { + (($self->{sock} // return)->can('stop_SSL') || $self->compressed) and return "$tag BAD TLS or compression already enabled\r\n"; - } - my $opt = $self->{imapd}->{accept_tls} or + $self->{imapd}->{ssl_ctx_opt} or return "$tag BAD can not initiate TLS negotiation\r\n"; $self->write(\"$tag OK begin TLS negotiation now\r\n"); - $self->{sock} = IO::Socket::SSL->start_SSL($sock, %$opt); + PublicInbox::TLS::start($self->{sock}, $self->{imapd}); $self->requeue if PublicInbox::DS::accept_tls_step($self); undef; }