{
adata->status = IMAP_FATAL;
- if ((adata->state >= IMAP_SELECTED) && (adata->reopen & IMAP_REOPEN_ALLOW))
+ if (!adata->mailbox)
+ return;
+
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ if (adata->state >= IMAP_SELECTED && (mdata->reopen & IMAP_REOPEN_ALLOW))
{
mx_fastclose_mailbox(adata->ctx);
mutt_socket_close(adata->conn);
mutt_debug(2, "Handling EXPUNGE\n");
- if (mutt_str_atoui(s, &exp_msn) < 0 || exp_msn < 1 || exp_msn > adata->max_msn)
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ if (mutt_str_atoui(s, &exp_msn) < 0 || exp_msn < 1 || exp_msn > mdata->max_msn)
return;
- e = adata->msn_index[exp_msn - 1];
+ e = mdata->msn_index[exp_msn - 1];
if (e)
{
/* imap_expunge_mailbox() will rewrite e->index.
}
/* decrement seqno of those above. */
- for (unsigned int cur = exp_msn; cur < adata->max_msn; cur++)
+ for (unsigned int cur = exp_msn; cur < mdata->max_msn; cur++)
{
- e = adata->msn_index[cur];
+ e = mdata->msn_index[cur];
if (e)
imap_edata_get(e)->msn--;
- adata->msn_index[cur - 1] = e;
+ mdata->msn_index[cur - 1] = e;
}
- adata->msn_index[adata->max_msn - 1] = NULL;
- adata->max_msn--;
+ mdata->msn_index[mdata->max_msn - 1] = NULL;
+ mdata->max_msn--;
- adata->reopen |= IMAP_EXPUNGE_PENDING;
+ mdata->reopen |= IMAP_EXPUNGE_PENDING;
}
/**
int rc;
unsigned int uid = 0;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
mutt_debug(2, "Handling VANISHED\n");
if (mutt_str_startswith(s, "(EARLIER)", CASE_IGNORE))
while ((rc = mutt_seqset_iterator_next(iter, &uid)) == 0)
{
- struct Email *e = mutt_hash_int_find(adata->uid_hash, uid);
+ struct Email *e = mutt_hash_int_find(mdata->uid_hash, uid);
if (!e)
continue;
e->index = INT_MAX;
imap_edata_get(e)->msn = 0;
- if ((exp_msn < 1) || (exp_msn > adata->max_msn))
+ if ((exp_msn < 1) || (exp_msn > mdata->max_msn))
{
mutt_debug(1, "VANISHED: msn for UID %u is incorrect.\n", uid);
continue;
}
- if (adata->msn_index[exp_msn - 1] != e)
+ if (mdata->msn_index[exp_msn - 1] != e)
{
mutt_debug(1, "VANISHED: msn_index for UID %u is incorrect.\n", uid);
continue;
}
- adata->msn_index[exp_msn - 1] = NULL;
+ mdata->msn_index[exp_msn - 1] = NULL;
if (!earlier)
{
/* decrement seqno of those above. */
- for (unsigned int cur = exp_msn; cur < adata->max_msn; cur++)
+ for (unsigned int cur = exp_msn; cur < mdata->max_msn; cur++)
{
- e = adata->msn_index[cur];
+ e = mdata->msn_index[cur];
if (e)
imap_edata_get(e)->msn--;
- adata->msn_index[cur - 1] = e;
+ mdata->msn_index[cur - 1] = e;
}
- adata->msn_index[adata->max_msn - 1] = NULL;
- adata->max_msn--;
+ mdata->msn_index[mdata->max_msn - 1] = NULL;
+ mdata->max_msn--;
}
}
if (rc < 0)
mutt_debug(1, "VANISHED: illegal seqset %s\n", s);
- adata->reopen |= IMAP_EXPUNGE_PENDING;
+ mdata->reopen |= IMAP_EXPUNGE_PENDING;
mutt_seqset_iterator_free(&iter);
}
int uid_checked = 0;
int server_changes = 0;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
mutt_debug(3, "Handling FETCH\n");
if (mutt_str_atoui(s, &msn) < 0)
return;
}
- if ((msn < 1) || (msn > adata->max_msn))
+ if ((msn < 1) || (msn > mdata->max_msn))
{
mutt_debug(3, "Skipping FETCH response - MSN %u out of range\n", msn);
return;
}
- e = adata->msn_index[msn - 1];
+ e = mdata->msn_index[msn - 1];
if (!e || !e->active)
{
mutt_debug(3, "Skipping FETCH response - MSN %u not in msn_index\n", msn);
{
/* If server flags could conflict with mutt's flags, reopen the mailbox. */
if (e->changed)
- adata->reopen |= IMAP_EXPUNGE_PENDING;
+ mdata->reopen |= IMAP_EXPUNGE_PENDING;
else
- adata->check_status = IMAP_FLAGS_PENDING;
+ mdata->check_status = IMAP_FLAGS_PENDING;
}
}
}
{
unsigned int uid;
struct Email *e = NULL;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
mutt_debug(2, "Handling SEARCH\n");
{
if (mutt_str_atoui(s, &uid) < 0)
continue;
- e = mutt_hash_int_find(adata->uid_hash, uid);
+ e = mutt_hash_int_find(mdata->uid_hash, uid);
if (e)
e->matched = true;
}
imap_unmunge_mbox_name(adata->unicode, mailbox);
}
- status = imap_mboxcache_get(adata, mailbox, 1);
+ struct ImapMboxData *mdata = imap_mdata_new(adata, mailbox);
+ status = imap_mboxcache_get(adata, mdata, true);
+ imap_mdata_free((void *) &mdata);
+
olduv = status->uidvalidity;
oldun = status->uidnext;
struct ImapAccountData *m_adata = imap_adata_get(np->m);
if (imap_account_match(&adata->conn_account, &m_adata->conn_account))
{
- struct ImapMboxData *mdata = imap_mdata_get(np->m);
- if (mdata && imap_mxcmp(mailbox, mdata->name) == 0)
+ struct ImapMboxData *mdata2 = imap_mdata_get(np->m);
+ if (mdata2 && imap_mxcmp(mailbox, mdata2->name) == 0)
{
mutt_debug(3, "Found %s in mailbox list (OV: %u ON: %u U: %d)\n",
mailbox, olduv, oldun, status->unseen);
mutt_debug(1, "Malformed EXISTS: '%s'\n", pn);
}
- if (!(adata->reopen & IMAP_EXPUNGE_PENDING) && count < adata->max_msn)
- {
- /* Notes 6.0.3 has a tendency to report fewer messages exist than
- * it should. */
- mutt_debug(1, "Message count is out of sync\n");
- return 0;
- }
- /* at least the InterChange server sends EXISTS messages freely,
- * even when there is no new mail */
- else if (count == adata->max_msn)
- mutt_debug(3, "superfluous EXISTS message.\n");
- else
+ if (adata->mailbox)
{
- if (!(adata->reopen & IMAP_EXPUNGE_PENDING))
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ if (!(mdata->reopen & IMAP_EXPUNGE_PENDING) && count < mdata->max_msn)
{
- mutt_debug(2, "New mail in %s - %d messages total.\n", adata->mbox_name, count);
- adata->reopen |= IMAP_NEWMAIL_PENDING;
+ /* Notes 6.0.3 has a tendency to report fewer messages exist than
+ * it should. */
+ mutt_debug(1, "Message count is out of sync\n");
+ return 0;
+ }
+ /* at least the InterChange server sends EXISTS messages freely,
+ * even when there is no new mail */
+ else if (count == mdata->max_msn)
+ mutt_debug(3, "superfluous EXISTS message.\n");
+ else
+ {
+ if (!(mdata->reopen & IMAP_EXPUNGE_PENDING))
+ {
+ mutt_debug(2, "New mail in %s - %d messages total.\n", mdata->name, count);
+ mdata->reopen |= IMAP_NEWMAIL_PENDING;
+ }
+ mdata->new_mail_count = count;
}
- adata->new_mail_count = count;
}
}
/* pn vs. s: need initial seqno */
*/
void imap_cmd_finish(struct ImapAccountData *adata)
{
+ struct ImapMboxData *mdata = NULL;
+
if (!adata)
return;
+ if (adata->mailbox)
+ mdata = adata->mailbox->mdata;
+
if (adata->status == IMAP_FATAL)
{
adata->closing = false;
adata->closing = false;
- if (adata->reopen & IMAP_REOPEN_ALLOW)
+ if (mdata && mdata->reopen & IMAP_REOPEN_ALLOW)
{
- unsigned int count = adata->new_mail_count;
+ unsigned int count = mdata->new_mail_count;
- if (!(adata->reopen & IMAP_EXPUNGE_PENDING) &&
- (adata->reopen & IMAP_NEWMAIL_PENDING) && count > adata->max_msn)
+ if (!(mdata->reopen & IMAP_EXPUNGE_PENDING) &&
+ (mdata->reopen & IMAP_NEWMAIL_PENDING) && count > mdata->max_msn)
{
/* read new mail messages */
mutt_debug(2, "Fetching new mail\n");
/* check_status: index uses imap_check_mailbox to detect
* whether the index needs updating */
- adata->check_status = IMAP_NEWMAIL_PENDING;
- imap_read_headers(adata, adata->max_msn + 1, count, false);
+ mdata->check_status = IMAP_NEWMAIL_PENDING;
+ imap_read_headers(adata, mdata->max_msn + 1, count, false);
}
- else if (adata->reopen & IMAP_EXPUNGE_PENDING)
+ else if (mdata->reopen & IMAP_EXPUNGE_PENDING)
{
mutt_debug(2, "Expunging mailbox\n");
imap_expunge_mailbox(adata);
/* Detect whether we've gotten unexpected EXPUNGE messages */
- if ((adata->reopen & IMAP_EXPUNGE_PENDING) && !(adata->reopen & IMAP_EXPUNGE_EXPECTED))
- adata->check_status = IMAP_EXPUNGE_PENDING;
- adata->reopen &=
+ if ((mdata->reopen & IMAP_EXPUNGE_PENDING) && !(mdata->reopen & IMAP_EXPUNGE_EXPECTED))
+ mdata->check_status = IMAP_EXPUNGE_PENDING;
+ mdata->reopen &=
~(IMAP_EXPUNGE_PENDING | IMAP_NEWMAIL_PENDING | IMAP_EXPUNGE_EXPECTED);
}
}
*
* TODO: ACL checks. Right now we assume if it exists we can mess with it.
*/
-static int imap_access2(struct ImapAccountData *adata, char *mailbox)
+static int imap_access2(struct ImapAccountData *adata, struct ImapMboxData *mdata)
{
+ struct ImapMboxData *selected_mdata = NULL;
char buf[LONG_STRING * 2];
- char mbox[LONG_STRING];
int rc;
+ if (adata->mailbox)
+ selected_mdata = adata->mailbox->mdata;
+
/* we may already be in the folder we're checking */
- if (mutt_str_strcmp(adata->mbox_name, mailbox) == 0)
+ if (selected_mdata && mutt_str_strcmp(selected_mdata->name, mdata->name) == 0)
return 0;
- if (imap_mboxcache_get(adata, mailbox, false))
+ if (imap_mboxcache_get(adata, mdata, false))
{
- mutt_debug(3, "found %s in cache\n", mailbox);
+ mutt_debug(3, "found %s in cache\n", mdata->name);
return 0;
}
- imap_munge_mbox_name(adata->unicode, mbox, sizeof(mbox), mailbox);
-
if (mutt_bit_isset(adata->capabilities, IMAP4REV1))
- snprintf(buf, sizeof(buf), "STATUS %s (UIDVALIDITY)", mbox);
+ snprintf(buf, sizeof(buf), "STATUS %s (UIDVALIDITY)", mdata->munge_name);
else if (mutt_bit_isset(adata->capabilities, STATUS))
- snprintf(buf, sizeof(buf), "STATUS %s (UID-VALIDITY)", mbox);
+ snprintf(buf, sizeof(buf), "STATUS %s (UID-VALIDITY)", mdata->munge_name);
else
{
mutt_debug(2, "STATUS not supported?\n");
rc = imap_exec(adata, buf, IMAP_CMD_FAIL_OK);
if (rc < 0)
{
- mutt_debug(1, "Can't check STATUS of %s\n", mbox);
+ mutt_debug(1, "Can't check STATUS of %s\n", mdata->munge_name);
return rc;
}
return 0;
if (imap_adata_find(path, &adata, &mdata) < 0)
return -1;
- rc = imap_access2(adata, mdata->name);
+ rc = imap_access2(adata, mdata);
imap_mdata_free((void *) &mdata);
return rc;
}
struct Email *e = NULL;
int cacheno;
short old_sort;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
#ifdef USE_HCACHE
- adata->hcache = imap_hcache_open(adata, NULL);
+ mdata->hcache = imap_hcache_open(adata, mdata);
#endif
old_sort = Sort;
imap_cache_del(adata, e);
#ifdef USE_HCACHE
- imap_hcache_del(adata, imap_edata_get(e)->uid);
+ imap_hcache_del(mdata, imap_edata_get(e)->uid);
#endif
/* free cached body from disk, if necessary */
cacheno = imap_edata_get(e)->uid % IMAP_CACHE_LEN;
- if (adata->cache[cacheno].uid == imap_edata_get(e)->uid &&
- adata->cache[cacheno].path)
+ if (mdata->cache[cacheno].uid == imap_edata_get(e)->uid &&
+ mdata->cache[cacheno].path)
{
- unlink(adata->cache[cacheno].path);
- FREE(&adata->cache[cacheno].path);
+ unlink(mdata->cache[cacheno].path);
+ FREE(&mdata->cache[cacheno].path);
}
- mutt_hash_int_delete(adata->uid_hash, imap_edata_get(e)->uid, e);
+ mutt_hash_int_delete(mdata->uid_hash, imap_edata_get(e)->uid, e);
imap_edata_free((void **) &e->edata);
}
}
#ifdef USE_HCACHE
- imap_hcache_close(adata);
+ imap_hcache_close(mdata);
#endif
/* We may be called on to expunge at any time. We can't rely on the caller
int imap_check_mailbox(struct Mailbox *m, bool force)
{
struct ImapAccountData *adata = imap_adata_get(m);
- return imap_check(adata, force);
+ return imap_check(adata, m->mdata, force);
}
/**
* imap_check - Check for new mail
* @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @param force Force a refresh
* @retval >0 Success, e.g. #MUTT_REOPENED
* @retval -1 Failure
*/
-int imap_check(struct ImapAccountData *adata, bool force)
+int imap_check(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool force)
{
- if (!adata || !adata->conn)
+ if (!adata || !adata->conn || !mdata)
return -1;
/* overload keyboard timeout to avoid many mailbox checks in a row.
* changes to process, since we can reopen here. */
imap_cmd_finish(adata);
- if (adata->check_status & IMAP_EXPUNGE_PENDING)
+ if (mdata->check_status & IMAP_EXPUNGE_PENDING)
result = MUTT_REOPENED;
- else if (adata->check_status & IMAP_NEWMAIL_PENDING)
+ else if (mdata->check_status & IMAP_NEWMAIL_PENDING)
result = MUTT_NEW_MAIL;
- else if (adata->check_status & IMAP_FLAGS_PENDING)
+ else if (mdata->check_status & IMAP_FLAGS_PENDING)
result = MUTT_FLAGS;
- adata->check_status = 0;
+ mdata->check_status = 0;
return result;
}
{
struct ImapAccountData *adata = NULL;
struct ImapMboxData *mdata = NULL;
+ struct ImapMboxData *selected_mdata = NULL;
char command[LONG_STRING * 2];
if (imap_prepare_mailbox(m))
mdata = m->mdata;
adata = m->account->adata;
+ if (adata->mailbox)
+ selected_mdata = adata->mailbox->mdata;
+
/* Don't issue STATUS on the selected mailbox, it will be NOOPed or
* IDLEd elsewhere.
* adata->mailbox may be NULL for connections other than the current
- * mailbox's, and shouldn't expand to INBOX in that case. #3216. */
- if (adata->mbox_name && (imap_mxcmp(mdata->name, adata->mbox_name) == 0))
+ * mailbox's.. #3216. */
+ if (selected_mdata && mdata == selected_mdata)
{
m->has_new = false;
return -1;
struct ImapAccountData *adata = NULL;
struct ImapMboxData *mdata = NULL;
+ struct ImapMboxData *selected_mdata = NULL;
char buf[LONG_STRING * 2];
struct ImapStatus *status = NULL;
if (imap_adata_find(path, &adata, &mdata) < 0)
return -1;
- /* We are in the folder we're polling - just return the mailbox count.
- *
- * Note that imap_mxcmp() converts NULL to "INBOX", so we need to
- * make sure the adata really is open to a folder. */
- if (adata->mailbox && !imap_mxcmp(mdata->name, adata->mbox_name))
+ if (adata->mailbox)
+ selected_mdata = adata->mailbox->mdata;
+
+ // We are in the folder we're polling - just return the mailbox count.
+ if (selected_mdata && selected_mdata == mdata)
{
imap_mdata_free((void **) &mdata);
return adata->mailbox->msg_count;
imap_exec(adata, buf, 0);
queued = 0;
- status = imap_mboxcache_get(adata, mdata->name, false);
+ status = imap_mboxcache_get(adata, mdata, false);
imap_mdata_free((void **) &mdata);
if (status)
return status->messages;
/**
* imap_mboxcache_get - Open an hcache for a mailbox
* @param adata Imap Account data
- * @param mbox Mailbox to cache
+ * @param mdata Imap Mailbox data to cache
* @param create Should it be created if it doesn't exist?
* @retval ptr Stats of cached mailbox
* @retval ptr Stats of new cache entry
* return cached mailbox stats or NULL if create is 0
*/
struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata,
- const char *mbox, bool create)
+ struct ImapMboxData *mdata, bool create)
{
struct ImapStatus *status = NULL;
struct ListNode *np = NULL;
{
status = (struct ImapStatus *) np->data;
- if (imap_mxcmp(mbox, status->name) == 0)
+ if (imap_mxcmp(mdata->name, status->name) == 0)
return status;
}
status = NULL;
if (create)
{
struct ImapStatus *scache = mutt_mem_calloc(1, sizeof(struct ImapStatus));
- scache->name = (char *) mbox;
+ scache->name = mdata->name;
mutt_list_insert_tail(&adata->mboxcache, (char *) scache);
- status = imap_mboxcache_get(adata, mbox, false);
- status->name = mutt_str_strdup(mbox);
+ status = imap_mboxcache_get(adata, mdata, false);
+ status->name = mutt_str_strdup(mdata->name);
}
#ifdef USE_HCACHE
- header_cache_t *hc = imap_hcache_open(adata, mbox);
+ header_cache_t *hc = imap_hcache_open(adata, mdata);
if (hc)
{
void *uidvalidity = mutt_hcache_fetch_raw(hc, "/UIDVALIDITY", 12);
mutt_hcache_free(hc, &uidnext);
mutt_hcache_free(hc, (void **) &modseq);
mutt_hcache_close(hc);
- return imap_mboxcache_get(adata, mbox, true);
+ return imap_mboxcache_get(adata, mdata, true);
}
status->uidvalidity = *(unsigned int *) uidvalidity;
status->uidnext = uidnext ? *(unsigned int *) uidnext : 0;
struct Mailbox *m = ctx->mailbox;
struct ImapAccountData *adata = imap_adata_get(m);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
if (adata->state < IMAP_SELECTED)
{
* to be changed. */
imap_allow_reopen(m);
- rc = imap_check(adata, false);
+ rc = imap_check(adata, mdata, false);
if (rc != 0)
return rc;
}
#ifdef USE_HCACHE
- adata->hcache = imap_hcache_open(adata, NULL);
+ mdata->hcache = imap_hcache_open(adata, mdata);
#endif
/* save messages with real (non-flag) changes */
{
imap_cache_del(adata, e);
#ifdef USE_HCACHE
- imap_hcache_del(adata, imap_edata_get(e)->uid);
+ imap_hcache_del(mdata, imap_edata_get(e)->uid);
#endif
}
if (e->active && e->changed)
{
#ifdef USE_HCACHE
- imap_hcache_put(adata, e);
+ imap_hcache_put(mdata, e);
#endif
/* if the message has been rethreaded or attachments have been deleted
* we delete the message and reupload it.
}
#ifdef USE_HCACHE
- imap_hcache_close(adata);
+ imap_hcache_close(mdata);
#endif
/* presort here to avoid doing 10 resorts in imap_exec_msgset */
{
mutt_message(_("Expunging messages from server..."));
/* Set expunge bit so we don't get spurious reopened messages */
- adata->reopen |= IMAP_EXPUNGE_EXPECTED;
+ mdata->reopen |= IMAP_EXPUNGE_EXPECTED;
if (imap_exec(adata, "EXPUNGE", 0) != 0)
{
- adata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
+ mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
imap_error(_("imap_sync_mailbox: EXPUNGE failed"), adata->buf);
return -1;
}
- adata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
+ mdata->reopen &= ~IMAP_EXPUNGE_EXPECTED;
}
if (expunge && close)
struct ImapStatus *status = NULL;
char buf[PATH_MAX];
- char bufout[PATH_MAX];
int count = 0;
int rc;
const char *condstore = NULL;
struct ImapAccountData *adata = m->account->adata;
struct ImapMboxData *mdata = m->mdata;
- FREE(&(adata->mbox_name));
- adata->mbox_name = mutt_str_strdup(mdata->name);
// TODO(sileht): store qualifed path in mdata ?
- imap_qualify_path(buf, sizeof(buf), &adata->conn_account, adata->mbox_name);
-
+ imap_qualify_path(buf, sizeof(buf), &adata->conn_account, mdata->name);
mutt_str_strfcpy(m->path, buf, sizeof(m->path));
mutt_str_strfcpy(m->realpath, m->path, sizeof(m->realpath));
/* clear mailbox status */
adata->status = 0;
memset(adata->mailbox->rights, 0, sizeof(adata->mailbox->rights));
- adata->new_mail_count = 0;
- adata->max_msn = 0;
- mutt_message(_("Selecting %s..."), adata->mbox_name);
- imap_munge_mbox_name(adata->unicode, buf, sizeof(buf), adata->mbox_name);
+ mutt_message(_("Selecting %s..."), mdata->name);
/* pipeline ACL test */
if (mutt_bit_isset(adata->capabilities, ACL))
{
- snprintf(bufout, sizeof(bufout), "MYRIGHTS %s", buf);
- imap_exec(adata, bufout, IMAP_CMD_QUEUE);
+ snprintf(buf, sizeof(buf), "MYRIGHTS %s", mdata->munge_name);
+ imap_exec(adata, buf, IMAP_CMD_QUEUE);
}
/* assume we have all rights if ACL is unavailable */
else
#endif
condstore = "";
- snprintf(bufout, sizeof(bufout), "%s %s%s",
- m->readonly ? "EXAMINE" : "SELECT", buf, condstore);
+ snprintf(buf, sizeof(buf), "%s %s%s", m->readonly ? "EXAMINE" : "SELECT",
+ mdata->munge_name, condstore);
adata->state = IMAP_SELECTED;
- imap_cmd_start(adata, bufout);
+ imap_cmd_start(adata, buf);
- status = imap_mboxcache_get(adata, adata->mbox_name, true);
+ status = imap_mboxcache_get(adata, mdata, true);
do
{
mutt_debug(3, "Getting mailbox UIDVALIDITY\n");
pc += 3;
pc = imap_next_word(pc);
- if (mutt_str_atoui(pc, &adata->uid_validity) < 0)
+ if (mutt_str_atoui(pc, &mdata->uid_validity) < 0)
goto fail;
- status->uidvalidity = adata->uid_validity;
+ status->uidvalidity = mdata->uid_validity;
}
else if (mutt_str_startswith(pc, "OK [UIDNEXT", CASE_IGNORE))
{
mutt_debug(3, "Getting mailbox UIDNEXT\n");
pc += 3;
pc = imap_next_word(pc);
- if (mutt_str_atoui(pc, &adata->uidnext) < 0)
+ if (mutt_str_atoui(pc, &mdata->uidnext) < 0)
goto fail;
- status->uidnext = adata->uidnext;
+ status->uidnext = mdata->uidnext;
}
else if (mutt_str_startswith(pc, "OK [HIGHESTMODSEQ", CASE_IGNORE))
{
mutt_debug(3, "Getting mailbox HIGHESTMODSEQ\n");
pc += 3;
pc = imap_next_word(pc);
- if (mutt_str_atoull(pc, &adata->modseq) < 0)
+ if (mutt_str_atoull(pc, &mdata->modseq) < 0)
goto fail;
- status->modseq = adata->modseq;
+ status->modseq = mdata->modseq;
}
else if (mutt_str_startswith(pc, "OK [NOMODSEQ", CASE_IGNORE))
{
mutt_debug(3, "Mailbox has NOMODSEQ set\n");
- status->modseq = adata->modseq = 0;
+ status->modseq = mdata->modseq = 0;
}
else
{
pc = imap_next_word(pc);
if (mutt_str_startswith(pc, "EXISTS", CASE_IGNORE))
{
- count = adata->new_mail_count;
- adata->new_mail_count = 0;
+ count = mdata->new_mail_count;
+ mdata->new_mail_count = 0;
}
}
} while (rc == IMAP_CMD_CONTINUE);
struct ImapAccountData *adata = m->account->adata;
struct ImapMboxData *mdata = m->mdata;
- rc = imap_access2(adata, mdata->name);
+ rc = imap_access2(adata, mdata);
if (rc == 0)
return 0;
if (rc == -1)
imap_allow_reopen(m);
struct ImapAccountData *adata = imap_adata_get(m);
- int rc = imap_check(adata, false);
+ int rc = imap_check(adata, m->mdata, false);
/* NOTE - ctx might have been changed at this point. In particular,
* m could be NULL. Beware. */
imap_disallow_reopen(m);
struct Mailbox *m = ctx->mailbox;
struct ImapAccountData *adata = imap_adata_get(m);
+
/* Check to see if the mailbox is actually open */
if (!adata)
return 0;
adata->state = IMAP_AUTHENTICATED;
}
- adata->reopen &= IMAP_REOPEN_ALLOW;
- FREE(&(adata->mbox_name));
mutt_list_free(&adata->flags);
adata->mailbox = NULL;
adata->ctx = NULL;
- mutt_hash_destroy(&adata->uid_hash);
- FREE(&adata->msn_index);
- adata->msn_index_size = 0;
- adata->max_msn = 0;
-
- for (int i = 0; i < IMAP_CACHE_LEN; i++)
- {
- if (adata->cache[i].path)
- {
- unlink(adata->cache[i].path);
- FREE(&adata->cache[i].path);
- }
- }
-
- mutt_bcache_close(&adata->bcache);
+ // TODO(sileht): As this is associated to a Mailbox we could keep it
+ // to not requery everything each time a mailbox is reopen. This need to be
+ // tested and we need to free this somewhere.
+ // For now free it each time we close the mailbox to keep the previous mutt
+ // behavior.
+ imap_mdata_free(&m->mdata);
}
return 0;
/* cache ImapStatus of visited mailboxes */
struct ListHead mboxcache;
- /* The following data is all specific to the currently SELECTED mbox */
char delim;
struct Context *ctx;
- struct Mailbox *mailbox;
- char *mbox_name;
- unsigned short check_status; /**< Flags, e.g. #IMAP_NEWMAIL_PENDING */
- unsigned char reopen; /**< Flags, e.g. #IMAP_REOPEN_ALLOW */
- unsigned int new_mail_count; /**< Set when EXISTS notifies of new mail */
- struct ImapCache cache[IMAP_CACHE_LEN];
- struct Hash *uid_hash;
- unsigned int uid_validity;
- unsigned int uidnext;
- unsigned long long modseq;
- struct Email **msn_index; /**< look up headers by (MSN-1) */
- size_t msn_index_size; /**< allocation size */
- unsigned int max_msn; /**< the largest MSN fetched so far */
- struct BodyCache *bcache;
+ struct Mailbox *mailbox; /* Current selected mailbox */
/* all folder flags - system AND custom flags */
struct ListHead flags;
-#ifdef USE_HCACHE
- header_cache_t *hcache;
-#endif
};
/**
char *name;
char *munge_name;
char *real_name;
+
+ unsigned char reopen; /**< Flags, e.g. #IMAP_REOPEN_ALLOW */
+ unsigned short check_status; /**< Flags, e.g. #IMAP_NEWMAIL_PENDING */
+ unsigned int new_mail_count; /**< Set when EXISTS notifies of new mail */
+ struct ImapCache cache[IMAP_CACHE_LEN];
+ struct Hash *uid_hash;
+ unsigned int uid_validity;
+ unsigned int uidnext;
+ unsigned long long modseq;
+ struct Email **msn_index; /**< look up headers by (MSN-1) */
+ size_t msn_index_size; /**< allocation size */
+ unsigned int max_msn; /**< the largest MSN fetched so far */
+ struct BodyCache *bcache;
+
+#ifdef USE_HCACHE
+ header_cache_t *hcache;
+#endif
};
/**
/* -- private IMAP functions -- */
/* imap.c */
-int imap_check(struct ImapAccountData *adata, bool force);
+int imap_check(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool force);
int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox);
int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char *newname);
-struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata, const char *mbox, bool create);
+struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata, struct ImapMboxData *mdata, bool create);
void imap_mboxcache_free(struct ImapAccountData *adata);
int imap_exec_msgset(struct ImapAccountData *adata, const char *pre, const char *post,
int flag, bool changed, bool invert);
struct ImapAccountData *imap_adata_get(struct Mailbox *m);
struct ImapMboxData *imap_mdata_get(struct Mailbox *m);
#ifdef USE_HCACHE
-header_cache_t *imap_hcache_open(struct ImapAccountData *adata, const char *path);
-void imap_hcache_close(struct ImapAccountData *adata);
-struct Email *imap_hcache_get(struct ImapAccountData *adata, unsigned int uid);
-int imap_hcache_put(struct ImapAccountData *adata, struct Email *e);
-int imap_hcache_del(struct ImapAccountData *adata, unsigned int uid);
-int imap_hcache_store_uid_seqset(struct ImapAccountData *adata);
-int imap_hcache_clear_uid_seqset(struct ImapAccountData *adata);
-char *imap_hcache_get_uid_seqset(struct ImapAccountData *adata);
+header_cache_t *imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata);
+void imap_hcache_close(struct ImapMboxData *mdata);
+struct Email *imap_hcache_get(struct ImapMboxData *mdata, unsigned int uid);
+int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e);
+int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid);
+int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata);
+int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata);
+char *imap_hcache_get_uid_seqset(struct ImapMboxData *mdata);
#endif
int imap_continue(const char *msg, const char *resp);
*/
static struct BodyCache *msg_cache_open(struct ImapAccountData *adata)
{
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
char mailbox[PATH_MAX];
- if (adata->bcache)
- return adata->bcache;
+ if (mdata->bcache)
+ return mdata->bcache;
- imap_cachepath(adata, adata->mbox_name, mailbox, sizeof(mailbox));
+ imap_cachepath(adata, mdata->name, mailbox, sizeof(mailbox));
return mutt_bcache_open(&adata->conn->account, mailbox);
}
if (!adata || !e)
return NULL;
- adata->bcache = msg_cache_open(adata);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ mdata->bcache = msg_cache_open(adata);
char id[64];
- snprintf(id, sizeof(id), "%u-%u", adata->uid_validity, imap_edata_get(e)->uid);
- return mutt_bcache_get(adata->bcache, id);
+ snprintf(id, sizeof(id), "%u-%u", mdata->uid_validity, imap_edata_get(e)->uid);
+ return mutt_bcache_get(mdata->bcache, id);
}
/**
if (!adata || !e)
return NULL;
- adata->bcache = msg_cache_open(adata);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ mdata->bcache = msg_cache_open(adata);
char id[64];
- snprintf(id, sizeof(id), "%u-%u", adata->uid_validity, imap_edata_get(e)->uid);
- return mutt_bcache_put(adata->bcache, id);
+ snprintf(id, sizeof(id), "%u-%u", mdata->uid_validity, imap_edata_get(e)->uid);
+ return mutt_bcache_put(mdata->bcache, id);
}
/**
if (!adata || !e)
return -1;
- adata->bcache = msg_cache_open(adata);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+
+ mdata->bcache = msg_cache_open(adata);
char id[64];
- snprintf(id, sizeof(id), "%u-%u", adata->uid_validity, imap_edata_get(e)->uid);
+ snprintf(id, sizeof(id), "%u-%u", mdata->uid_validity, imap_edata_get(e)->uid);
- return mutt_bcache_commit(adata->bcache, id);
+ return mutt_bcache_commit(mdata->bcache, id);
}
/**
{
unsigned int uv, uid;
struct ImapAccountData *adata = data;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
if (sscanf(id, "%u-%u", &uv, &uid) != 2)
return 0;
/* bad UID */
- if (uv != adata->uid_validity || !mutt_hash_int_find(adata->uid_hash, uid))
+ if (uv != mdata->uid_validity || !mutt_hash_int_find(mdata->uid_hash, uid))
mutt_bcache_del(bcache, id);
return 0;
*/
static void alloc_msn_index(struct ImapAccountData *adata, size_t msn_count)
{
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
size_t new_size;
- if (msn_count <= adata->msn_index_size)
+ if (msn_count <= mdata->msn_index_size)
return;
/* This is a conservative check to protect against a malicious imap
/* Add a little padding, like mx_allloc_memory() */
new_size = msn_count + 25;
- if (!adata->msn_index)
- adata->msn_index = mutt_mem_calloc(new_size, sizeof(struct Email *));
+ if (!mdata->msn_index)
+ mdata->msn_index = mutt_mem_calloc(new_size, sizeof(struct Email *));
else
{
- mutt_mem_realloc(&adata->msn_index, sizeof(struct Email *) * new_size);
- memset(adata->msn_index + adata->msn_index_size, 0,
- sizeof(struct Email *) * (new_size - adata->msn_index_size));
+ mutt_mem_realloc(&mdata->msn_index, sizeof(struct Email *) * new_size);
+ memset(mdata->msn_index + mdata->msn_index_size, 0,
+ sizeof(struct Email *) * (new_size - mdata->msn_index_size));
}
- adata->msn_index_size = new_size;
+ mdata->msn_index_size = new_size;
}
/**
*/
static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_count)
{
- if (!adata->uid_hash)
- adata->uid_hash = mutt_hash_int_new(MAX(6 * msn_count / 5, 30), 0);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+ if (!mdata->uid_hash)
+ mdata->uid_hash = mutt_hash_int_new(MAX(6 * msn_count / 5, 30), 0);
}
/**
static void imap_fetch_msn_seqset(struct Buffer *b, struct ImapAccountData *adata,
unsigned int msn_begin, unsigned int msn_end)
{
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
int chunks = 0;
int state = 0; /* 1: single msn, 2: range of msn */
unsigned int range_begin = 0;
for (unsigned int msn = msn_begin; msn <= (msn_end + 1); msn++)
{
- if ((msn <= msn_end) && !adata->msn_index[msn - 1])
+ if ((msn <= msn_end) && !mdata->msn_index[msn - 1])
{
switch (state)
{
char buf[LONG_STRING];
struct Mailbox *m = adata->mailbox;
+ struct ImapMboxData *mdata = m->mdata;
int idx = m->msg_count;
/* L10N:
continue;
}
- if (adata->msn_index[h.data->msn - 1])
+ if (mdata->msn_index[h.data->msn - 1])
{
mutt_debug(2, "skipping hcache FETCH for duplicate message %d\n", h.data->msn);
continue;
}
- m->hdrs[idx] = imap_hcache_get(adata, h.data->uid);
+ m->hdrs[idx] = imap_hcache_get(mdata, h.data->uid);
if (m->hdrs[idx])
{
- adata->max_msn = MAX(adata->max_msn, h.data->msn);
- adata->msn_index[h.data->msn - 1] = m->hdrs[idx];
- mutt_hash_int_insert(adata->uid_hash, h.data->uid, m->hdrs[idx]);
+ mdata->max_msn = MAX(mdata->max_msn, h.data->msn);
+ mdata->msn_index[h.data->msn - 1] = m->hdrs[idx];
+ mutt_hash_int_insert(mdata->uid_hash, h.data->uid, m->hdrs[idx]);
m->hdrs[idx]->index = idx;
/* messages which have not been expunged are ACTIVE (borrowed from mh
/* If this is the first time we are fetching, we need to
* store the current state of flags back into the header cache */
if (!eval_condstore && store_flag_updates)
- imap_hcache_put(adata, m->hdrs[idx]);
+ imap_hcache_put(mdata, m->hdrs[idx]);
h.data = NULL;
idx++;
mutt_debug(2, "Reading uid seqset from header cache\n");
struct Mailbox *m = adata->mailbox;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
unsigned int msn = 1;
struct SeqsetIterator *iter = mutt_seqset_iterator_new(uid_seqset);
{
/* The seqset may contain more headers than the fetch request, so
* we need to watch and reallocate the context and msn_index */
- if (msn > adata->msn_index_size)
+ if (msn > mdata->msn_index_size)
alloc_msn_index(adata, msn);
- struct Email *e = imap_hcache_get(adata, uid);
+ struct Email *e = imap_hcache_get(mdata, uid);
if (e)
{
- adata->max_msn = MAX(adata->max_msn, msn);
- adata->msn_index[msn - 1] = e;
+ mdata->max_msn = MAX(mdata->max_msn, msn);
+ mdata->msn_index[msn - 1] = e;
if (m->msg_count >= m->hdrmax)
mx_alloc_memory(m);
edata->msn = msn;
edata->uid = uid;
- mutt_hash_int_insert(adata->uid_hash, uid, e);
+ mutt_hash_int_insert(mdata->uid_hash, uid, e);
m->size += e->content->length;
m->hdrs[m->msg_count++] = e;
unsigned int header_msn = 0;
struct Mailbox *m = adata->mailbox;
+ struct ImapMboxData *mdata = m->mdata;
/* L10N: Fetching IMAP flag changes, using the CONDSTORE extension */
mutt_progress_init(&progress, _("Fetching flag updates..."),
if (!isdigit((unsigned char) *fetch_buf) || (mutt_str_atoui(fetch_buf, &header_msn) < 0))
continue;
- if ((header_msn < 1) || (header_msn > msn_end) || !adata->msn_index[header_msn - 1])
+ if ((header_msn < 1) || (header_msn > msn_end) || !mdata->msn_index[header_msn - 1])
{
mutt_debug(1, "skipping CONDSTORE flag update for unknown message number %u\n", header_msn);
continue;
}
- imap_hcache_put(adata, adata->msn_index[header_msn - 1]);
+ imap_hcache_put(mdata, mdata->msn_index[header_msn - 1]);
}
/* The IMAP flag setting as part of cmd_parse_fetch() ends up
* flipping these on. */
- adata->check_status &= ~IMAP_FLAGS_PENDING;
+ mdata->check_status &= ~IMAP_FLAGS_PENDING;
m->changed = false;
/* VANISHED handling: we need to empty out the messages */
- if (adata->reopen & IMAP_EXPUNGE_PENDING)
+ if (mdata->reopen & IMAP_EXPUNGE_PENDING)
{
- imap_hcache_close(adata);
+ imap_hcache_close(mdata);
imap_expunge_mailbox(adata);
- adata->hcache = imap_hcache_open(adata, NULL);
- adata->reopen &= ~IMAP_EXPUNGE_PENDING;
+ mdata->hcache = imap_hcache_open(adata, mdata);
+ mdata->reopen &= ~IMAP_EXPUNGE_PENDING;
}
return 0;
"X-ORIGINAL-TO";
struct Mailbox *m = adata->mailbox;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
int idx = m->msg_count;
if (mutt_bit_isset(adata->capabilities, IMAP4REV1))
}
/* May receive FLAGS updates in a separate untagged response (#2935) */
- if (adata->msn_index[h.data->msn - 1])
+ if (mdata->msn_index[h.data->msn - 1])
{
mutt_debug(2, "skipping FETCH response for duplicate message %d\n",
h.data->msn);
m->hdrs[idx] = mutt_email_new();
- adata->max_msn = MAX(adata->max_msn, h.data->msn);
- adata->msn_index[h.data->msn - 1] = m->hdrs[idx];
- mutt_hash_int_insert(adata->uid_hash, h.data->uid, m->hdrs[idx]);
+ mdata->max_msn = MAX(mdata->max_msn, h.data->msn);
+ mdata->msn_index[h.data->msn - 1] = m->hdrs[idx];
+ mutt_hash_int_insert(mdata->uid_hash, h.data->uid, m->hdrs[idx]);
m->hdrs[idx]->index = idx;
/* messages which have not been expunged are ACTIVE (borrowed from mh
m->size += h.content_length;
#ifdef USE_HCACHE
- imap_hcache_put(adata, m->hdrs[idx]);
+ imap_hcache_put(mdata, m->hdrs[idx]);
#endif /* USE_HCACHE */
m->msg_count++;
* middle of a FETCH. But just to be cautious, use the current state
* of max_msn, not fetch_msn_end to set the next start range.
*/
- if (adata->reopen & IMAP_NEWMAIL_PENDING)
+ if (mdata->reopen & IMAP_NEWMAIL_PENDING)
{
/* update to the last value we actually pulled down */
- fetch_msn_end = adata->max_msn;
- msn_begin = adata->max_msn + 1;
- msn_end = adata->new_mail_count;
+ fetch_msn_end = mdata->max_msn;
+ msn_begin = mdata->max_msn + 1;
+ msn_end = mdata->new_mail_count;
while (msn_end > m->hdrmax)
mx_alloc_memory(m);
alloc_msn_index(adata, msn_end);
- adata->reopen &= ~IMAP_NEWMAIL_PENDING;
- adata->new_mail_count = 0;
+ mdata->reopen &= ~IMAP_NEWMAIL_PENDING;
+ mdata->new_mail_count = 0;
}
}
#endif /* USE_HCACHE */
struct Mailbox *m = adata->mailbox;
+ struct ImapMboxData *mdata = m->mdata;
/* make sure context has room to hold the mailbox */
while (msn_end > m->hdrmax)
imap_alloc_uid_hash(adata, msn_end);
oldmsgcount = m->msg_count;
- adata->reopen &= ~(IMAP_REOPEN_ALLOW | IMAP_NEWMAIL_PENDING);
- adata->new_mail_count = 0;
+ mdata->reopen &= ~(IMAP_REOPEN_ALLOW | IMAP_NEWMAIL_PENDING);
+ mdata->new_mail_count = 0;
#ifdef USE_HCACHE
- adata->hcache = imap_hcache_open(adata, NULL);
+ mdata->hcache = imap_hcache_open(adata, mdata);
- if (adata->hcache && initial_download)
+ if (mdata->hcache && initial_download)
{
- uid_validity = mutt_hcache_fetch_raw(adata->hcache, "/UIDVALIDITY", 12);
- puidnext = mutt_hcache_fetch_raw(adata->hcache, "/UIDNEXT", 8);
+ uid_validity = mutt_hcache_fetch_raw(mdata->hcache, "/UIDVALIDITY", 12);
+ puidnext = mutt_hcache_fetch_raw(mdata->hcache, "/UIDNEXT", 8);
if (puidnext)
{
uidnext = *(unsigned int *) puidnext;
- mutt_hcache_free(adata->hcache, &puidnext);
+ mutt_hcache_free(mdata->hcache, &puidnext);
}
- if (adata->modseq)
+ if (mdata->modseq)
{
if (mutt_bit_isset(adata->capabilities, CONDSTORE) && ImapCondStore)
has_condstore = true;
has_qresync = true;
}
- if (uid_validity && uidnext && (*(unsigned int *) uid_validity == adata->uid_validity))
+ if (uid_validity && uidnext && (*(unsigned int *) uid_validity == mdata->uid_validity))
{
evalhc = true;
- pmodseq = mutt_hcache_fetch_raw(adata->hcache, "/MODSEQ", 7);
+ pmodseq = mutt_hcache_fetch_raw(mdata->hcache, "/MODSEQ", 7);
if (pmodseq)
{
hc_modseq = *pmodseq;
- mutt_hcache_free(adata->hcache, (void **) &pmodseq);
+ mutt_hcache_free(mdata->hcache, (void **) &pmodseq);
}
if (hc_modseq)
{
if (has_qresync)
{
- uid_seqset = imap_hcache_get_uid_seqset(adata);
+ uid_seqset = imap_hcache_get_uid_seqset(mdata);
if (uid_seqset)
eval_qresync = true;
}
eval_condstore = true;
}
}
- mutt_hcache_free(adata->hcache, &uid_validity);
+ mutt_hcache_free(mdata->hcache, &uid_validity);
}
if (evalhc)
{
goto bail;
}
- if ((eval_condstore || eval_qresync) && (hc_modseq != adata->modseq))
+ if ((eval_condstore || eval_qresync) && (hc_modseq != mdata->modseq))
{
if (read_headers_condstore_qresync_updates(adata, msn_end, uidnext,
hc_modseq, eval_qresync) < 0)
/* Look for the first empty MSN and start there */
while (msn_begin <= msn_end)
{
- if (!adata->msn_index[msn_begin - 1])
+ if (!mdata->msn_index[msn_begin - 1])
break;
msn_begin++;
}
if (read_headers_fetch_new(adata, msn_begin, msn_end, evalhc, &maxuid, initial_download) < 0)
goto bail;
- if (maxuid && (status = imap_mboxcache_get(adata, adata->mbox_name, 0)) &&
+ if (maxuid && (status = imap_mboxcache_get(adata, mdata, 0)) &&
(status->uidnext < maxuid + 1))
{
status->uidnext = maxuid + 1;
}
#ifdef USE_HCACHE
- mutt_hcache_store_raw(adata->hcache, "/UIDVALIDITY", 12, &adata->uid_validity,
- sizeof(adata->uid_validity));
- if (maxuid && adata->uidnext < maxuid + 1)
+ mutt_hcache_store_raw(mdata->hcache, "/UIDVALIDITY", 12, &mdata->uid_validity,
+ sizeof(mdata->uid_validity));
+ if (maxuid && mdata->uidnext < maxuid + 1)
{
- mutt_debug(2, "Overriding UIDNEXT: %u -> %u\n", adata->uidnext, maxuid + 1);
- adata->uidnext = maxuid + 1;
+ mutt_debug(2, "Overriding UIDNEXT: %u -> %u\n", mdata->uidnext, maxuid + 1);
+ mdata->uidnext = maxuid + 1;
}
- if (adata->uidnext > 1)
+ if (mdata->uidnext > 1)
{
- mutt_hcache_store_raw(adata->hcache, "/UIDNEXT", 8, &adata->uidnext,
- sizeof(adata->uidnext));
+ mutt_hcache_store_raw(mdata->hcache, "/UIDNEXT", 8, &mdata->uidnext,
+ sizeof(mdata->uidnext));
}
/* We currently only sync CONDSTORE and QRESYNC on the initial download.
{
if (has_condstore || has_qresync)
{
- mutt_hcache_store_raw(adata->hcache, "/MODSEQ", 7, &adata->modseq,
- sizeof(adata->modseq));
+ mutt_hcache_store_raw(mdata->hcache, "/MODSEQ", 7, &mdata->modseq,
+ sizeof(mdata->modseq));
}
else
- mutt_hcache_delete(adata->hcache, "/MODSEQ", 7);
+ mutt_hcache_delete(mdata->hcache, "/MODSEQ", 7);
if (has_qresync)
- imap_hcache_store_uid_seqset(adata);
+ imap_hcache_store_uid_seqset(mdata);
else
- imap_hcache_clear_uid_seqset(adata);
+ imap_hcache_clear_uid_seqset(mdata);
}
#endif /* USE_HCACHE */
mx_update_context(adata->ctx, m->msg_count - oldmsgcount);
}
- adata->reopen |= IMAP_REOPEN_ALLOW;
+ mdata->reopen |= IMAP_REOPEN_ALLOW;
retval = msn_end;
bail:
#ifdef USE_HCACHE
- imap_hcache_close(adata);
+ imap_hcache_close(mdata);
FREE(&uid_seqset);
#endif /* USE_HCACHE */
{
if (!adata || !e)
return -1;
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
- adata->bcache = msg_cache_open(adata);
+ mdata->bcache = msg_cache_open(adata);
char id[64];
- snprintf(id, sizeof(id), "%u-%u", adata->uid_validity, imap_edata_get(e)->uid);
- return mutt_bcache_del(adata->bcache, id);
+ snprintf(id, sizeof(id), "%u-%u", mdata->uid_validity, imap_edata_get(e)->uid);
+ return mutt_bcache_del(mdata->bcache, id);
}
/**
*/
int imap_cache_clean(struct ImapAccountData *adata)
{
- adata->bcache = msg_cache_open(adata);
- mutt_bcache_list(adata->bcache, msg_cache_clean_cb, adata);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+ mdata->bcache = msg_cache_open(adata);
+ mutt_bcache_list(mdata->bcache, msg_cache_clean_cb, adata);
return 0;
}
struct Mailbox *m = ctx->mailbox;
struct ImapAccountData *adata = imap_adata_get(m);
+ struct ImapMboxData *mdata = m->mdata;
struct Email *e = m->hdrs[msgno];
msg->fp = msg_cache_get(adata, e);
/* we still do some caching even if imap_cachedir is unset */
/* see if we already have the message in our cache */
cacheno = imap_edata_get(e)->uid % IMAP_CACHE_LEN;
- cache = &adata->cache[cacheno];
+ cache = &mdata->cache[cacheno];
if (cache->path)
{
imap_mboxcache_free(adata);
mutt_buffer_free(&adata->cmdbuf);
FREE(&adata->buf);
- mutt_bcache_close(&adata->bcache);
FREE(&adata->cmds);
if (adata->conn)
imap_munge_mbox_name(adata->unicode, buf, sizeof(buf), mdata->name);
mdata->munge_name = mutt_str_strdup(buf);
+ mdata->reopen &= IMAP_REOPEN_ALLOW;
+
return mdata;
}
struct ImapMboxData *mdata = *ptr;
+ for (int i = 0; i < IMAP_CACHE_LEN; i++)
+ {
+ if (mdata->cache[i].path)
+ {
+ unlink(mdata->cache[i].path);
+ FREE(&mdata->cache[i].path);
+ }
+ }
+
+ mutt_bcache_close(&mdata->bcache);
+ mutt_hash_destroy(&mdata->uid_hash);
FREE(&mdata->name);
FREE(&mdata->real_name);
FREE(&mdata->munge_name);
+ FREE(&mdata->msn_index);
FREE(ptr);
}
/**
* imap_msn_index_to_uid_seqset - Convert MSN index of UIDs to Seqset
* @param b Buffer for the result
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
*
* Generates a seqseq of the UIDs in msn_index to persist in the header cache.
* Empty spots are stored as 0.
*/
-static void imap_msn_index_to_uid_seqset(struct Buffer *b, struct ImapAccountData *adata)
+static void imap_msn_index_to_uid_seqset(struct Buffer *b, struct ImapMboxData *mdata)
{
int first = 1, state = 0;
unsigned int cur_uid = 0, last_uid = 0;
unsigned int range_begin = 0, range_end = 0;
- for (unsigned int msn = 1; msn <= adata->max_msn + 1; msn++)
+ for (unsigned int msn = 1; msn <= mdata->max_msn + 1; msn++)
{
bool match = false;
- if (msn <= adata->max_msn)
+ if (msn <= mdata->max_msn)
{
- struct Email *cur_header = adata->msn_index[msn - 1];
+ struct Email *cur_header = mdata->msn_index[msn - 1];
cur_uid = cur_header ? imap_edata_get(cur_header)->uid : 0;
if (!state || (cur_uid && ((cur_uid - 1) == last_uid)))
match = true;
/**
* imap_hcache_open - Open a header cache
* @param adata Imap Account data
- * @param path Path to the header cache
+ * @param mdata Imap Mailbox data
* @retval ptr HeaderCache
* @retval NULL Failure
*/
-header_cache_t *imap_hcache_open(struct ImapAccountData *adata, const char *path)
+header_cache_t *imap_hcache_open(struct ImapAccountData *adata, struct ImapMboxData *mdata)
{
struct Url url;
char cachepath[PATH_MAX];
char mbox[PATH_MAX];
- if (path)
- imap_cachepath(adata, path, mbox, sizeof(mbox));
- else if (adata->mailbox)
- {
- struct ImapMboxData *mdata = imap_mdata_get(adata->mailbox);
- imap_cachepath(adata, mdata->name, mbox, sizeof(mbox));
- }
- else
- return NULL;
+ imap_cachepath(adata, mdata->name, mbox, sizeof(mbox));
if (strstr(mbox, "/../") || (strcmp(mbox, "..") == 0) || (strncmp(mbox, "../", 3) == 0))
return NULL;
/**
* imap_hcache_close - Close the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
*/
-void imap_hcache_close(struct ImapAccountData *adata)
+void imap_hcache_close(struct ImapMboxData *mdata)
{
- if (!adata->hcache)
+ if (!mdata->hcache)
return;
- mutt_hcache_close(adata->hcache);
- adata->hcache = NULL;
+ mutt_hcache_close(mdata->hcache);
+ mdata->hcache = NULL;
}
/**
* imap_hcache_get - Get a header cache entry by its UID
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @param uid UID to find
* @retval ptr Email Header
* @retval NULL Failure
*/
-struct Email *imap_hcache_get(struct ImapAccountData *adata, unsigned int uid)
+struct Email *imap_hcache_get(struct ImapMboxData *mdata, unsigned int uid)
{
char key[16];
void *uv = NULL;
struct Email *e = NULL;
- if (!adata->hcache)
+ if (!mdata->hcache)
return NULL;
sprintf(key, "/%u", uid);
- uv = mutt_hcache_fetch(adata->hcache, key, imap_hcache_keylen(key));
+ uv = mutt_hcache_fetch(mdata->hcache, key, imap_hcache_keylen(key));
if (uv)
{
- if (*(unsigned int *) uv == adata->uid_validity)
+ if (*(unsigned int *) uv == mdata->uid_validity)
e = mutt_hcache_restore(uv);
else
mutt_debug(3, "hcache uidvalidity mismatch: %u\n", *(unsigned int *) uv);
- mutt_hcache_free(adata->hcache, &uv);
+ mutt_hcache_free(mdata->hcache, &uv);
}
return e;
/**
* imap_hcache_put - Add an entry to the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @param e Email
* @retval 0 Success
* @retval -1 Failure
*/
-int imap_hcache_put(struct ImapAccountData *adata, struct Email *e)
+int imap_hcache_put(struct ImapMboxData *mdata, struct Email *e)
{
char key[16];
- if (!adata->hcache)
+ if (!mdata->hcache)
return -1;
sprintf(key, "/%u", imap_edata_get(e)->uid);
- return mutt_hcache_store(adata->hcache, key, imap_hcache_keylen(key), e, adata->uid_validity);
+ return mutt_hcache_store(mdata->hcache, key, imap_hcache_keylen(key), e, mdata->uid_validity);
}
/**
* imap_hcache_del - Delete an item from the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @param uid UID of entry to delete
* @retval 0 Success
* @retval -1 Failure
*/
-int imap_hcache_del(struct ImapAccountData *adata, unsigned int uid)
+int imap_hcache_del(struct ImapMboxData *mdata, unsigned int uid)
{
char key[16];
- if (!adata->hcache)
+ if (!mdata->hcache)
return -1;
sprintf(key, "/%u", uid);
- return mutt_hcache_delete(adata->hcache, key, imap_hcache_keylen(key));
+ return mutt_hcache_delete(mdata->hcache, key, imap_hcache_keylen(key));
}
/**
* imap_hcache_store_uid_seqset - Store a UID Sequence Set in the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @retval 0 Success
* @retval -1 Error
*/
-int imap_hcache_store_uid_seqset(struct ImapAccountData *adata)
+int imap_hcache_store_uid_seqset(struct ImapMboxData *mdata)
{
- if (!adata->hcache)
+ if (!mdata->hcache)
return -1;
struct Buffer *b = mutt_buffer_new();
/* The seqset is likely large. Preallocate to reduce reallocs */
mutt_buffer_increase_size(b, HUGE_STRING);
- imap_msn_index_to_uid_seqset(b, adata);
+ imap_msn_index_to_uid_seqset(b, mdata);
size_t seqset_size = b->dptr - b->data;
if (seqset_size == 0)
b->data[0] = '\0';
- int rc = mutt_hcache_store_raw(adata->hcache, "/UIDSEQSET", 10, b->data, seqset_size + 1);
+ int rc = mutt_hcache_store_raw(mdata->hcache, "/UIDSEQSET", 10, b->data, seqset_size + 1);
mutt_debug(5, "Stored /UIDSEQSET %s\n", b->data);
mutt_buffer_free(&b);
return rc;
/**
* imap_hcache_clear_uid_seqset - Delete a UID Sequence Set from the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @retval 0 Success
* @retval -1 Error
*/
-int imap_hcache_clear_uid_seqset(struct ImapAccountData *adata)
+int imap_hcache_clear_uid_seqset(struct ImapMboxData *mdata)
{
- if (!adata->hcache)
+ if (!mdata->hcache)
return -1;
- return mutt_hcache_delete(adata->hcache, "/UIDSEQSET", 10);
+ return mutt_hcache_delete(mdata->hcache, "/UIDSEQSET", 10);
}
/**
* imap_hcache_get_uid_seqset - Get a UID Sequence Set from the header cache
- * @param adata Imap Account data
+ * @param mdata Imap Mailbox data
* @retval ptr UID Sequence Set
* @retval NULL Error
*/
-char *imap_hcache_get_uid_seqset(struct ImapAccountData *adata)
+char *imap_hcache_get_uid_seqset(struct ImapMboxData *mdata)
{
- if (!adata->hcache)
+ if (!mdata->hcache)
return NULL;
- char *hc_seqset = mutt_hcache_fetch_raw(adata->hcache, "/UIDSEQSET", 10);
+ char *hc_seqset = mutt_hcache_fetch_raw(mdata->hcache, "/UIDSEQSET", 10);
char *seqset = mutt_str_strdup(hc_seqset);
- mutt_hcache_free(adata->hcache, (void **) &hc_seqset);
+ mutt_hcache_free(mdata->hcache, (void **) &hc_seqset);
mutt_debug(5, "Retrieved /UIDSEQSET %s\n", NONULL(seqset));
return seqset;
continue;
struct ImapAccountData *adata = np->adata;
- if (!adata)
+ if (!adata || !adata->mailbox)
continue;
if ((adata->state >= IMAP_AUTHENTICATED) && (now >= (adata->lastread + ImapKeepalive)))
{
- imap_check(adata, true);
+ struct ImapMboxData *mdata = adata->mailbox->mdata;
+ imap_check(adata, mdata, true);
}
}
}
if (!m)
return;
struct ImapAccountData *adata = imap_adata_get(m);
- if (!adata)
+ if (!adata || !adata->mailbox || adata->mailbox != m)
return;
- if (adata->mailbox == m)
- adata->reopen |= IMAP_REOPEN_ALLOW;
+ struct ImapMboxData *mdata = m->mdata;
+ mdata->reopen |= IMAP_REOPEN_ALLOW;
}
/**
if (!m)
return;
struct ImapAccountData *adata = imap_adata_get(m);
- if (!adata)
+ if (!adata || !adata->mailbox || adata->mailbox != m)
return;
- if (adata->mailbox == m)
- adata->reopen &= ~IMAP_REOPEN_ALLOW;
+ struct ImapMboxData *mdata = m->mdata;
+ mdata->reopen &= ~IMAP_REOPEN_ALLOW;
}
/**