-# Copyright (C) 2020-2021 all contributors <meta@public-inbox.org>
+# Copyright (C) all contributors <meta@public-inbox.org>
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
#
# Each instance of this represents an IMAP client connected to
use PublicInbox::Eml;
use PublicInbox::EmlContentFoo qw(parse_content_disposition);
use PublicInbox::DS qw(now);
-use PublicInbox::Syscall qw(EPOLLIN EPOLLONESHOT);
use PublicInbox::GitAsyncCat;
use Text::ParseWords qw(parse_line);
use Errno qw(EAGAIN);
my $valid_range = '[0-9]+|[0-9]+:[0-9]+|[0-9]+:\*';
$valid_range = qr/\A(?:$valid_range)(?:,(?:$valid_range))*\z/;
-sub greet ($) {
+sub do_greet {
my ($self) = @_;
my $capa = capa($self);
$self->write(\"* OK [$capa] public-inbox-imapd ready\r\n");
}
-sub new ($$$) {
- my ($class, $sock, $imapd) = @_;
- my $self = bless { imapd => $imapd }, 'PublicInbox::IMAP_preauth';
- my $ev = EPOLLIN;
- my $wbuf;
- if ($sock->can('accept_SSL') && !$sock->accept_SSL) {
- return CORE::close($sock) if $! != EAGAIN;
- $ev = PublicInbox::TLS::epollbit() or return CORE::close($sock);
- $wbuf = [ \&PublicInbox::DS::accept_tls_step, \&greet ];
- }
- $self->SUPER::new($sock, $ev | EPOLLONESHOT);
- if ($wbuf) {
- $self->{wbuf} = $wbuf;
- } else {
- greet($self);
- }
- $self;
+sub new {
+ my (undef, $sock, $imapd) = @_;
+ (bless { imapd => $imapd }, 'PublicInbox::IMAP_preauth')->greet($sock)
}
sub logged_in { 1 }
$self->{ibx} = $ibx;
$self->{uo2m} = uo2m_ary_new($self, \$exists);
} else {
- $exists = $over->imap_exists;
+ my $uid_end = $uid_base + UID_SLICE;
+ $exists = $over->imap_exists($uid_base, $uid_end);
}
ensure_slices_exist($self->{imapd}, $ibx, $over->max);
} else {
join('', @hold);
}
-sub requeue_once ($) {
- my ($self) = @_;
- # COMPRESS users all share the same DEFLATE context.
- # Flush it here to ensure clients don't see
- # each other's data
- $self->zflush;
-
- # no recursion, schedule another call ASAP,
- # but only after all pending writes are done.
- # autovivify wbuf:
- my $new_size = push(@{$self->{wbuf}}, \&long_step);
-
- # wbuf may be populated by $cb, no need to rearm if so:
- $self->requeue if $new_size == 1;
-}
-
sub fetch_run_ops {
my ($self, $smsg, $bref, $ops, $partial) = @_;
my $uid = $smsg->{num};
# it's possible to have TOCTOU if an admin runs
# public-inbox-(edit|purge), just move onto the next message
warn "E: $smsg->{blob} missing in $ibx->{inboxdir}\n";
- return requeue_once($self);
+ return $self->requeue_once;
} else {
$smsg->{blob} eq $oid or die "BUG: $smsg->{blob} != $oid";
}
\&fetch_blob_cb, $fetch_arg);
}
fetch_run_ops($self, $smsg, $bref, $ops, $partial);
- $pre ? $self->zflush : requeue_once($self);
+ $pre ? $self->zflush : $self->requeue_once;
}
sub emit_rfc822 {
# prepares an index for BODY[$SECTION_IDX] fetches
sub eml_body_idx ($$) {
my ($eml, $section_idx) = @_;
- my $idx = $eml->{imap_all_parts} //= do {
+ my $idx = $eml->{imap_all_parts} // do {
my $all = {};
$eml->each_part(\&eml_index_offs_i, $all, 0, 1);
# top-level of multipart, BODY[0] not allowed (nz-number)
delete $all->{0};
- $all;
+ $eml->{imap_all_parts} = $all;
};
$idx->{$section_idx};
}
search_common($self, $tag, $query, 1);
}
-sub args_ok ($$) { # duplicated from PublicInbox::NNTP
- my ($cb, $argc) = @_;
- my $tot = prototype $cb;
- my ($nreq, undef) = split(';', $tot);
- $nreq = ($nreq =~ tr/$//) - 1;
- $tot = ($tot =~ tr/$//) - 1;
- ($argc <= $tot && $argc >= $nreq);
-}
-
# returns 1 if we can continue, 0 if not due to buffered writes or disconnect
sub process_line ($$) {
my ($self, $l) = @_;
$self->close;
} elsif ($more) { # $self->{wbuf}:
# control passed to ibx_async_cat if $more == \undef
- requeue_once($self) if !ref($more);
+ $self->requeue_once($self) if !ref($more);
} else { # all done!
delete $self->{long_cb};
my $elapsed = now() - $t0;
sub compressed { undef }
-sub zflush {} # overridden by IMAPdeflate
-
# RFC 4978
sub cmd_compress ($$$) {
my ($self, $tag, $alg) = @_;