/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "str.h"
#include "mail-index-modseq.h"
#include "imap-arg.h"
#include "imap-seqset.h"
#include "imap-util.h"
#include "imapc-mail.h"
#include "imapc-msgmap.h"
#include "imapc-list.h"
#include "imapc-search.h"
#include "imapc-sync.h"
#include "imapc-storage.h"
const char *reason, ...)
{
const char *errmsg;
if (!mbox->initial_sync_done) {
/* we failed during initial sync. need to rebuild indexes if
we want to get this fixed */
} else {
/* maybe the remote server is buggy and has become confused.
try reconnecting. */
}
}
static struct mail_index_view *
{
}
{
return;
}
{
unsigned int n;
int ret;
}
if (ret < 0)
return ret;
}
bool *changes_r)
{
int ret = 0;
;
/* ignore any changes done during SELECT */
} else {
ret = -1;
}
}
/* delayed expunges - commit them now in a separate
transaction. Reopen mbox->sync_view to see changes
committed in delayed_sync_trans. */
if (imapc_mailbox_commit_delayed_expunges(mbox) < 0)
ret = -1;
}
return ret;
}
{
}
{
}
}
static void
{
if (mbox->sync_next_lseq == 0) {
/* FETCH n:*, not 1:* */
return;
}
/* if we haven't seen FETCH reply for some messages at the end of
mailbox they've been externally expunged. */
/* another process already added new messages to index
that our IMAP connection hasn't seen yet */
break;
}
}
mbox->sync_next_lseq = 0;
mbox->sync_next_rseq = 0;
}
static void
void *context)
{
case IMAPC_COMMAND_STATE_OK:
break;
case IMAPC_COMMAND_STATE_NO:
break;
break;
default:
break;
}
}
static void
{
if (mbox->exists_count == 0) {
/* empty mailbox - no point in fetching anything */
return;
}
if (mbox->state_fetching_uid1) {
/* retrying after reconnection - don't send duplicate */
return;
}
if (imapc_mailbox_has_modseqs(mbox)) {
}
/* these can be efficiently fetched among flags and
stored into cache */
}
/* do this only for the \All mailbox */
(flags & MAILBOX_SPECIALUSE_ALL) != 0)
}
if (first_uid == 1) {
/* only the FETCH 1:* is retriable - others will be retried
by the 1:* after the reconnection */
}
}
static void
struct imapc_mailbox *mbox)
{
return;
if (mbox->exists_received &&
/* ignore all except the first EXISTS reply (returned by
SELECT) */
return;
}
/* We don't know the latest flags, refresh them. */
}
}
{
const unsigned int *kw_idx;
unsigned int i, j, count;
return FALSE;
/* there are normally only a few keywords, so O(n^2) is fine */
for (i = 0; i < count; i++) {
for (j = 0; j < count; j++) {
break;
}
if (j == count)
return FALSE;
}
return TRUE;
}
static int
{
*lseq_r = 0;
/* Receiving a FETCH for a message that EXISTS hasn't
announced yet. MS Exchange has a bug where our UID FETCH
request sometimes sends replies where sequences are above
EXISTS value, but their UIDs are for existing messages.
We'll just ignore these replies. */
return 0;
}
/* This was the initial attempt at catching the above
MS Exchange bug, but the above one appears to catch all
these cases. But keep it here just in case. */
"(seq=%u,%u vs uid=%u,%u)",
return -1;
}
if (fetch_uid != 0 &&
/* if we know the UID, use own own generated rseq instead of
the potentially broken rseq that the server sent. */
rseq = fixed_rseq;
}
"FETCH UID mismatch (%u != %u)",
return -1;
}
/* probably a flag update for a message we haven't yet
received our initial UID FETCH for. we should get
another one. */
if (fetch_uid == 0)
return 0;
"FETCH returned wrong sequence for UID %u "
return -1;
}
"Expunged message reappeared in session "
"(uid=%u < next_uid=%u)",
return -1;
} else {
/* newly seen message */
/* message is already added to index */
} else {
}
}
return 0;
}
struct imapc_mailbox *mbox)
{
unsigned int i, j;
return;
return;
return;
return;
seen_flags = TRUE;
return;
if (atom[0] == '\\')
else {
/* keyword */
}
}
/* (modseq-number) */
return;
return;
!mbox->initial_sync_done) {
return;
return;
have_labels = TRUE;
}
}
}
if (fetch_uid == 0 &&
/* UID missing and we're not tracking MSNs */
return;
}
return;
/* remember for STATUS_FIRST_RECENT_UID */
}
/* FIXME: we should ideally also pass these through so they show up
to clients. */
flags &= ~MAIL_RECENT;
/* if this is a reply to some FETCH request, update the mail's fields */
}
}
if (lseq == 0) {
/* already expunged by another session */
mbox->sync_next_rseq++;
return;
}
}
/* we're doing the initial full sync of mails. expunge any
mails that no longer exist. */
mbox->sync_next_lseq++;
}
mbox->sync_next_rseq++;
mbox->sync_next_lseq++;
}
}
if (seen_flags) {
&old_kws);
if (have_labels) {
/* add keyword for mails that have GMail labels.
this can be used for "All Mail" mailbox migrations
with dsync */
atom = "$GMailHaveLabels";
}
}
}
if (modseq != 0) {
}
lseq, guid_cache_idx)) {
}
}
}
struct imapc_mailbox *mbox)
{
return;
mbox->prev_skipped_rseq = 0;
mbox->prev_skipped_uid = 0;
if (mbox->exists_count == 0) {
"EXPUNGE received for empty mailbox");
return;
}
mbox->exists_count--;
/* we haven't even seen this message yet */
return;
}
/* this message exists only in this transaction. lib-index
can't currently handle expunging anything except the last
appended message in a transaction, and fixing it would be
quite a lot of trouble. so instead we'll just delay doing
this expunge until after the current transaction has been
committed. */
} else {
/* already expunged by another session */
}
}
static void
struct imapc_mailbox *mbox)
{
const char *atom;
unsigned int n;
unsigned int pop3_deleted_kw_idx;
/* It should contain ALL <seqset> or nonexistent if nothing matched */
return;
i_error("Invalid gmail-pop3 ESEARCH reply");
return;
}
/* we haven't even seen this message yet */
break;
}
continue;
/* add the pop3_deleted_flag */
}
}
struct imapc_mailbox *mbox)
{
}
struct imapc_mailbox *mbox)
{
const char *str;
return;
/* ESEARCH begins with (TAG <tag>) */
return;
/* for now the only ESEARCH reply that we have is for getting GMail's
list of hidden POP3 messages. */
else
}
{
mbox->sync_uid_validity != 0) {
if (hdr->uid_validity != 0) {
/* uidvalidity changed, reset the entire mailbox */
}
}
}
static void
struct imapc_mailbox *mbox)
{
uid_validity == 0)
return;
}
}
static void
struct imapc_mailbox *mbox)
{
return;
}
static void
struct imapc_mailbox *mbox)
{
return;
}
static void
struct imapc_mailbox *mbox)
{
const char *flag;
unsigned int idx;
return;
mbox->permanent_flags = 0;
continue;
else if (*flag == '\\')
else {
/* we'll simply make sure that it exists in the index */
}
}
}
const char *key,
{
}
const char *key,
{
}
{
}