Commit Graph

1259 Commits

Author SHA1 Message Date
Oswald Buddenhagen
9b72e10320 make IMAP error messages less confusing
don't print the status, as the user doesn't really care whether it's
NO or BAD. more importantly, "NO LOGIN failed" is a rather misleading
thing to report.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
3aead33008 rework IMAP list parsing
replace the "DOM-like" model with a "streaming" model, i.e., the tokens
are now immediately processed by stateful callbacks as they are found.
this avoids plenty of allocations and copies (though not of the message
contents, yet).
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
f748bd45df tweak debug output for IMAP literals
- short literals are now printed even with only -Dn.
  this ensures that we see all parts of, for example, LIST responses.
  we use xprintf() for that, so we don't mess up the -Dn output in case
  the literal contains something unexpected (we don't care with -DN).
- omitted bytes are now indicated.
- missing trailing newlines are now "pretty-printed".
- long literals are now printed in chunks as we receive them. this
  makes the output messier, but it's necessary for an upcoming change,
  and, on the upside, we'll get better indication when the transfer
  gets stuck in the middle of a message.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
80831e50b9 add xprintf()
this introduces a "commit" callback to the xprintf kernel, to avoid
pointlessly assembling a temporary output string prior to printing it.

one could lift the buffer limitations by introducing a "segment"
callback instead, but that would slow down xvasprintf() due to the
higher callback rate, for no good reason.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
0079ec774a add escaping of non-printable & non-ASCII characters to xvasprintf() 2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
57173bd289 restructure xvasprintf() for uniformity
%\\s now supports length limitations, and \\ on other format specifiers
is now ignored (like .* already was on non-strings).
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
1a89f8a178 move imap_vprintf() to util.c and rename it to xvasprintf()
it's currently used only by IMAP, but it's logically low-level.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
859b7dd7f2 try to avoid extra syscalls when reading sockets
so far we shifted down the buffered data only when we ran out of space.
however, that may cause chopping up the actual socket read, which is a
bad trade-off with avoiding a moderate-sized memmove. so try to keep
enough space for the anticipated read size.

note that this ignores the zlib path, as that always does full-size
socket reads into z_buf, and saving inflate() calls seems pointless.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
ac3b5186b0 don't notify about socket reads that fall short of expectations
this will prospectively make the debug output less messy.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
96b1e52802 make socket_read()'s interface more like socket_read_line()'s
return a pointer into the internal buffer rather than copying into a
user-supplied one. this permits zero-copy in future use cases.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
6f15980cd9 socket_read_line(): reset buffer offset when no bytes are left
socket_read() already did that.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
69653aafeb beautify socket_read_line() somewhat
- use more appropriate name for socket object
- localize some variable declarations
- denoise the code by using more local variables
- don't pointlessly do stuff when we're failing anyway
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
bc3145617a add input length argument to map_name()
... and use it when parsing IMAP LIST responses.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
5243c69863 require IMAP4rev1 capability
technically, we should have been doing that since the beginning, but as
there is IMAP4rev2 now, it might actually matter (in about a decade,
when servers start dropping backwards compat ...).
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
4a5c79993c optimize IMAP flag parsing
uppercase the reference strings and utilize already known string
lengths.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
6b9d4311d2 make IMAP parsing case insensitive
it's easy to overlook, but the spec demands this. we got away with it so
far, as everyone just uses UPPERCASE ... for the things we use so far.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
8d9c68f73a optimize string operations in IMAP parser
the string length is knowable in advance everywhere, so we can use that
for strdups and short-circuiting comparisons.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
c5e967f94d add support for LITERAL- extension
it's the same as LITERAL+, only with a strongly limited payload size.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
5048521d79 make sure that all IMAP lists are parsed
... even if we ignore their contents, as they may (hypothetically)
contain literals, which are relevant for the stream syntax.

amends 6fd4e8de2.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
a07be5f175 improve error reporting from IMAP list parsing
so far, we'd print only a generic message - except in two cases, where
the generic error would be preceded by a specific one. now we always
print a single reasonably specific message.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
c7f50a3069 simplify parsing responses with multiple IMAP lists
the callbacks took the current parsing position only to pass it on to
the next list parse. so instead, store it in the state, and have a
separate function for continuation.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
ad8520b741 revamp sending of IMAP commands with literals
include the literal's length into the command itself, so error messages
become clearer. the commands are initially built for LITERAL+, and are
"edited down" right before sending if necessary.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
abd31aad61 simplify assembly of IMAP APPEND commands
treat the date string the same as the flag string.

amends eb1f1076.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
4ae0159132 handle tagged BAD [TOOBIG] server responses
some servers consider attempts to APPEND too big messages to be BAD
commands, rather than just NO-worthy ones. so just pretend that we did
in fact get a NO, and carry on.

this was tested with gmail. if we run into servers that don't send the
expected response code, we will need to relax the condition.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
5e5c7fb508 free IMAP command's payload prior to invoking its completion callback
otherwise the synching may livelock due to failing to schedule follow-up
commands, thinking the buffers are still full. of course, this is
relevant only for commands that failed early and thus didn't free the
payload right after submission already - which will be possible only
after the next commit.
2022-06-19 16:10:57 +02:00
Oswald Buddenhagen
1225f0b86b add ExpungeSolo option
REFMAIL: CAOgBZNonT0s0b_yPs2vx81Ru3cQp5M93xpZ3syWBW-2CNoX_ow@mail.gmail.com
2022-06-19 16:10:54 +02:00
Oswald Buddenhagen
95a22739fa don't UID EXPUNGE too many messages
we didn't check that the UIDs are adjacent, so we might have caught
not fetched deleted messages between two fetched messages below the
bulk load range.

checking adjacency of UIDs would make expunges in the bulk range (which
is likely to be full of holes) rather inefficient. so we use sequence
numbers instead.

this is admittedly a rather academical fix ...

amends 18225344.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
1631361f66 revamp handling of expunged messages
try to purge sync entries based on which messages are *actually*
expunged, rather than those that are *expected* to be expunged.

to save network bandwidth, the IMAP driver doesn't report all expunges,
so some entry purges would be delayed - potentially indefinitely, e.g.,
when only --pull-new --push is used, or Trash isn't used (nor
ExpungeSolo, prospectively). so keep a fallback path to avoid this.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
1a1ac25bc8 track IMAP message sequence numbers (and therefore expunges) 2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
df4e6383f5 track number of messages in IMAP stores
... rather than calculating it on the fly. for efficiency.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
6fe7172901 moan about trashing in non-UIDPLUS boxes
... as that's inherently racy, as the manual says.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
edbf9a35da use UID EXPUNGE also when trashing remotely
amends 2f0fbcd3.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
04c7126ce9 add autotest for syncing non-UIDPLUS stores 2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
767a318eea add new sync operation 'Old'
this is essentially the same as 'New', but for previously seen messages,
such as those that would have been instantly expunged (because they were
marked as deleted), those that we failed to store for some reason, and
already expired ones that are now flagged.

REFMAIL: CAOgBZNonT0s0b_yPs2vx81Ru3cQp5M93xpZ3syWBW-2CNoX_ow@mail.gmail.com
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
a8e145e589 split OPEN_PAIRED from OPEN_OLD, and rename OPEN_OLD_IDS accordingly
this emphasizes the non-complementarity to OPEN_NEW.
the "real" OPEN_OLD is currently used only for trashing.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
d77d67c948 concentrate calculation of minimal loaded UID in load_box()
so it's in one place with the maximal one, sans the one-sided
preparation of the bulk range + exception list.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
e98aed87f0 silently reinterpret --full
change it from --{push,pull} to --{new,gone,flags,upgrade}.
that alone doesn't change anything; combining it with any other option
would cause a complaint anyway.

this enables us to introduce --{push,pull}-full, which will matter when
--full doesn't actually include all type flags any more, as we'll then
be able to combine it with the extra type flag(s). in the same vein, we
now advertize "Sync Full" instead of "Sync All" (both continue to be
recognized).
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
58564e4f76 rename Delete to Gone
this is more symmetrical with New, and results in some less dodgy
grammar. it also avoids confusion with the \Deleted flag.

fwiw, the pedantically correct name would be Expunges, but that's
confusingly close to the target-side expunge options. also, it's longer.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
6308a7f41b rename ReNew to Upgrade
that's what it really has been for a while now.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
8f39d06015 fix mixing MaxMessages with MaxSize
this is actually a useful combination for resource-constrained devices.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
882c9825cd fix handling of 'seen' flag wrt placeholders
while we don't want to propagate seeing _from_ the placeholder, we do
want to propagate it _to_ it, and consequently also un-seeing from it.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
cb687f1bee make MaxSize ignore source-side message flagging
when propagation of too big messages was entirely suppressed, the only
way to force it was flagging the source message. however, now that we
have placeholders that can be flagged to trigger full propagation, it's
rather pointless to keep the old method working, and still doing it
does in fact confuse users, see for example
REFMAIL: CAOgBZNq_a9yKcq8Jw5y9VS6p2Se8mD7gkf6vPr_KU0taAWuGZQ@mail.gmail.com

to avoid this, we now almost completely shadow the regular meaning of
flagging - it basically becomes a non-synchronizable flag until the
placeholder is upgraded.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
e6a15bee59 make sure we fetch source flags when expiring while pulling new
otherwise important messages may be incorrectly aborted.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
3febb16fd5 fix off-by-one when loading messages outside the bulk range
this would lead to a bogus deletion being propagated to the near side.
2022-06-19 16:10:01 +02:00
Oswald Buddenhagen
0089f49c4a fix expiration when syncing only new messages
this was broken by commit de6dc699 - we now iterated only over far-side
messages, which we don't necessarily load, unlike the near-side ones
(which we need to do to know their current importance).

fix by iterating over sync entries instead of messages, which basically
restores the pre-19128f15 state in that regard. the minor catch here is
that we now need an auxiliary array to sort the sync entries by UIDs. on
the upside, we can also use it to avoid repeated calculation of the
flags.
2022-06-19 16:10:00 +02:00
Oswald Buddenhagen
4ddacef2c1 fix expiration completion during --noop run
make sure that an expiration calculation run is performed if ongoing
expiration transactions have been loaded from the journal. this has the
nice side effect of centralizing the regular trigger condition as well.

flags_set_p2() is also adjusted to query S_NEXPIRE only if an expiration
is actually ongoing, like the flag propagation submission loop already
did.

this went unnoticed, because expiration upon arrival of new messages
wasn't autotested at all - despite being the common case.
2022-06-19 16:10:00 +02:00
Oswald Buddenhagen
ef43021f26 don't pointlessly load near-side new messages when expiring
we don't count them towards the total anyway (as they are unpaired).
2022-06-19 16:10:00 +02:00
Oswald Buddenhagen
fe4e478e95 fix expiration completion after external expunge
when the expiration is interrupted, but an external expunge removes the
near-side message before we resume, we would just drop the transaction,
resulting in an "unmarked" orphan.

a corner case is an expiration that finishes, but initially isn't
expunged (probably due to an interruption), followed by an unexpiration
that gets interrupted, and the message being expunged externally
(because it's still marked as deleted). we obviously can't complete
that transaction without re-propagating the message, so effectively
cancel it instead.
2022-06-19 16:10:00 +02:00
Oswald Buddenhagen
1ca278ad0d simplify journaling of expiring unborn messages
don't use a separate journal command anymore, but handle them like
regular expirations, and let the entry purge loop at the end cleanup
them.
2022-06-19 16:10:00 +02:00
Oswald Buddenhagen
eab3874918 orphan/prune sync entries also if messages were expunged externally
deletions we propagated ourselves are implicitly covered by that as
well, so we don't need to record them separately anymore.
2022-06-19 16:10:00 +02:00