]> granicus.if.org Git - neomutt/commitdiff
imap: move some adata attributes to mdata
authorMehdi Abaakouk <sileht@sileht.net>
Fri, 16 Nov 2018 14:05:53 +0000 (15:05 +0100)
committerRichard Russon <rich@flatcap.org>
Sat, 17 Nov 2018 17:54:22 +0000 (17:54 +0000)
imap/command.c
imap/imap.c
imap/imap_private.h
imap/message.c
imap/util.c

index c1da91f1e75bb739108380dd4ee194dcfaf9562a..d09dad74bb25cab17da9340ec9959907d483215b 100644 (file)
@@ -158,7 +158,12 @@ static void cmd_handle_fatal(struct ImapAccountData *adata)
 {
   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);
@@ -248,10 +253,12 @@ static void cmd_parse_expunge(struct ImapAccountData *adata, const char *s)
 
   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.
@@ -262,18 +269,18 @@ static void cmd_parse_expunge(struct ImapAccountData *adata, const char *s)
   }
 
   /* 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;
 }
 
 /**
@@ -290,6 +297,8 @@ static void cmd_parse_vanished(struct ImapAccountData *adata, char *s)
   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))
@@ -318,7 +327,7 @@ static void cmd_parse_vanished(struct ImapAccountData *adata, char *s)
 
   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;
 
@@ -330,39 +339,39 @@ static void cmd_parse_vanished(struct ImapAccountData *adata, char *s)
     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);
 }
@@ -384,6 +393,8 @@ static void cmd_parse_fetch(struct ImapAccountData *adata, char *s)
   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)
@@ -392,13 +403,13 @@ static void cmd_parse_fetch(struct ImapAccountData *adata, char *s)
     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);
@@ -500,9 +511,9 @@ static void cmd_parse_fetch(struct ImapAccountData *adata, char *s)
     {
       /* 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;
     }
   }
 }
@@ -746,6 +757,7 @@ static void cmd_parse_search(struct ImapAccountData *adata, const char *s)
 {
   unsigned int uid;
   struct Email *e = NULL;
+  struct ImapMboxData *mdata = adata->mailbox->mdata;
 
   mutt_debug(2, "Handling SEARCH\n");
 
@@ -753,7 +765,7 @@ static void cmd_parse_search(struct ImapAccountData *adata, const char *s)
   {
     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;
   }
@@ -806,7 +818,10 @@ static void cmd_parse_status(struct ImapAccountData *adata, char *s)
     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;
 
@@ -869,8 +884,8 @@ static void cmd_parse_status(struct ImapAccountData *adata, char *s)
     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);
@@ -968,25 +983,30 @@ static int cmd_handle_untagged(struct ImapAccountData *adata)
         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 */
@@ -1297,9 +1317,14 @@ int imap_exec(struct ImapAccountData *adata, const char *cmdstr, int flags)
  */
 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;
@@ -1315,28 +1340,28 @@ void imap_cmd_finish(struct ImapAccountData *adata)
 
   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);
     }
   }
index 10c52aacaa9e447448806707ba50f8786d40abf4..e5b6e019be2f323c5e050cd69812203bf6260a29 100644 (file)
@@ -598,28 +598,29 @@ static int complete_hosts(char *buf, size_t buflen)
  *
  * 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");
@@ -629,7 +630,7 @@ static int imap_access2(struct ImapAccountData *adata, char *mailbox)
   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;
@@ -677,7 +678,7 @@ int imap_access(const char *path)
   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;
 }
@@ -839,9 +840,10 @@ void imap_expunge_mailbox(struct ImapAccountData *adata)
   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;
@@ -861,19 +863,19 @@ void imap_expunge_mailbox(struct ImapAccountData *adata)
 
       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);
     }
@@ -901,7 +903,7 @@ void imap_expunge_mailbox(struct ImapAccountData *adata)
   }
 
 #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
@@ -1272,19 +1274,20 @@ int imap_sync_message_for_copy(struct ImapAccountData *adata, struct Email *e,
 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.
@@ -1325,14 +1328,14 @@ int imap_check(struct ImapAccountData *adata, bool force)
    * 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;
 }
@@ -1351,6 +1354,7 @@ int imap_mailbox_check(struct Mailbox *m, bool check_stats)
 {
   struct ImapAccountData *adata = NULL;
   struct ImapMboxData *mdata = NULL;
+  struct ImapMboxData *selected_mdata = NULL;
   char command[LONG_STRING * 2];
 
   if (imap_prepare_mailbox(m))
@@ -1362,11 +1366,14 @@ int imap_mailbox_check(struct Mailbox *m, bool check_stats)
   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;
@@ -1421,17 +1428,18 @@ int imap_status(const char *path, bool queue)
 
   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;
@@ -1461,7 +1469,7 @@ int imap_status(const char *path, bool queue)
     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;
@@ -1472,7 +1480,7 @@ int imap_status(const char *path, bool queue)
 /**
  * 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
@@ -1481,7 +1489,7 @@ int imap_status(const char *path, bool queue)
  * 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;
@@ -1489,7 +1497,7 @@ struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata,
   {
     status = (struct ImapStatus *) np->data;
 
-    if (imap_mxcmp(mbox, status->name) == 0)
+    if (imap_mxcmp(mdata->name, status->name) == 0)
       return status;
   }
   status = NULL;
@@ -1498,14 +1506,14 @@ struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata,
   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);
@@ -1519,7 +1527,7 @@ struct ImapStatus *imap_mboxcache_get(struct ImapAccountData *adata,
         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;
@@ -1853,6 +1861,7 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
   struct Mailbox *m = ctx->mailbox;
 
   struct ImapAccountData *adata = imap_adata_get(m);
+  struct ImapMboxData *mdata = adata->mailbox->mdata;
 
   if (adata->state < IMAP_SELECTED)
   {
@@ -1864,7 +1873,7 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
    * to be changed. */
   imap_allow_reopen(m);
 
-  rc = imap_check(adata, false);
+  rc = imap_check(adata, mdata, false);
   if (rc != 0)
     return rc;
 
@@ -1893,7 +1902,7 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
   }
 
 #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 */
@@ -1905,14 +1914,14 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
     {
       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.
@@ -1931,7 +1940,7 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
   }
 
 #ifdef USE_HCACHE
-  imap_hcache_close(adata);
+  imap_hcache_close(mdata);
 #endif
 
   /* presort here to avoid doing 10 resorts in imap_exec_msgset */
@@ -2003,14 +2012,14 @@ int imap_sync_mailbox(struct Context *ctx, bool expunge, bool close)
   {
     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)
@@ -2160,7 +2169,6 @@ static int imap_mbox_open(struct Context *ctx)
 
   struct ImapStatus *status = NULL;
   char buf[PATH_MAX];
-  char bufout[PATH_MAX];
   int count = 0;
   int rc;
   const char *condstore = NULL;
@@ -2172,11 +2180,8 @@ static int imap_mbox_open(struct Context *ctx)
   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));
 
@@ -2191,17 +2196,14 @@ static int imap_mbox_open(struct Context *ctx)
   /* 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
@@ -2236,14 +2238,14 @@ static int imap_mbox_open(struct Context *ctx)
 #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
   {
@@ -2286,40 +2288,40 @@ static int imap_mbox_open(struct Context *ctx)
       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);
@@ -2416,7 +2418,7 @@ static int imap_mbox_open_append(struct Mailbox *m, int flags)
   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)
@@ -2449,7 +2451,7 @@ static int imap_mbox_check(struct Context *ctx, int *index_hint)
 
   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);
@@ -2468,6 +2470,7 @@ static int imap_mbox_close(struct Context *ctx)
   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;
@@ -2494,27 +2497,16 @@ static int imap_mbox_close(struct Context *ctx)
       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;
index f51261e39b8abcf70b739ac9fc9103b8f9fb2ea7..44035207debe3b0ed81dcaa2c36572e4b767bbf7 100644 (file)
@@ -248,29 +248,12 @@ struct ImapAccountData
   /* 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
 };
 
 /**
@@ -283,6 +266,23 @@ struct ImapMboxData
   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
 };
 
 /**
@@ -302,10 +302,10 @@ struct SeqsetIterator
 
 /* -- 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);
@@ -348,14 +348,14 @@ int imap_msg_commit(struct Mailbox *m, struct Message *msg);
 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);
index f610f4f139a080aba20b63aa42d38e0cdbb00e5b..640086965818c82d039fe6ac74cc6d5ec3cc7994 100644 (file)
@@ -113,12 +113,13 @@ struct ImapEmailData *imap_edata_get(struct Email *e)
  */
 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);
 }
@@ -135,10 +136,12 @@ static FILE *msg_cache_get(struct ImapAccountData *adata, struct Email *e)
   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);
 }
 
 /**
@@ -153,10 +156,12 @@ static FILE *msg_cache_put(struct ImapAccountData *adata, struct Email *e)
   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);
 }
 
 /**
@@ -171,11 +176,13 @@ static int msg_cache_commit(struct ImapAccountData *adata, struct Email *e)
   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);
 }
 
 /**
@@ -186,12 +193,13 @@ static int msg_cache_clean_cb(const char *id, struct BodyCache *bcache, void *da
 {
   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;
@@ -523,9 +531,10 @@ static bool query_abort_header_download(struct ImapAccountData *adata)
  */
 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
@@ -540,16 +549,16 @@ static void alloc_msn_index(struct ImapAccountData *adata, size_t msn_count)
   /* 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;
 }
 
 /**
@@ -562,8 +571,9 @@ static void alloc_msn_index(struct ImapAccountData *adata, size_t msn_count)
  */
 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);
 }
 
 /**
@@ -583,6 +593,7 @@ static void imap_alloc_uid_hash(struct ImapAccountData *adata, unsigned int msn_
 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;
@@ -590,7 +601,7 @@ static void imap_fetch_msn_seqset(struct Buffer *b, struct ImapAccountData *adat
 
   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)
       {
@@ -693,6 +704,7 @@ static int read_headers_normal_eval_cache(struct ImapAccountData *adata,
   char buf[LONG_STRING];
 
   struct Mailbox *m = adata->mailbox;
+  struct ImapMboxData *mdata = m->mdata;
   int idx = m->msg_count;
 
   /* L10N:
@@ -743,18 +755,18 @@ static int read_headers_normal_eval_cache(struct ImapAccountData *adata,
         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
@@ -794,7 +806,7 @@ static int read_headers_normal_eval_cache(struct ImapAccountData *adata,
         /* 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++;
@@ -829,6 +841,7 @@ static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *
 
   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);
@@ -839,14 +852,14 @@ static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *
   {
     /* 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);
@@ -866,7 +879,7 @@ static int read_headers_qresync_eval_cache(struct ImapAccountData *adata, char *
 
       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;
@@ -901,6 +914,7 @@ static int read_headers_condstore_qresync_updates(struct ImapAccountData *adata,
   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..."),
@@ -934,27 +948,27 @@ static int read_headers_condstore_qresync_updates(struct ImapAccountData *adata,
     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;
@@ -989,6 +1003,7 @@ static int read_headers_fetch_new(struct ImapAccountData *adata, unsigned int ms
       "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))
@@ -1083,7 +1098,7 @@ static int read_headers_fetch_new(struct ImapAccountData *adata, unsigned int ms
         }
 
         /* 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);
@@ -1092,9 +1107,9 @@ static int read_headers_fetch_new(struct ImapAccountData *adata, unsigned int ms
 
         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
@@ -1128,7 +1143,7 @@ static int read_headers_fetch_new(struct ImapAccountData *adata, unsigned int ms
         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++;
@@ -1149,17 +1164,17 @@ static int read_headers_fetch_new(struct ImapAccountData *adata, unsigned int ms
      * 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;
     }
   }
 
@@ -1208,6 +1223,7 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
 #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)
@@ -1216,23 +1232,23 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
   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;
@@ -1245,20 +1261,20 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
         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;
         }
@@ -1267,7 +1283,7 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
           eval_condstore = true;
       }
     }
-    mutt_hcache_free(adata->hcache, &uid_validity);
+    mutt_hcache_free(mdata->hcache, &uid_validity);
   }
   if (evalhc)
   {
@@ -1283,7 +1299,7 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
         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)
@@ -1295,7 +1311,7 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
     /* 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++;
     }
@@ -1305,24 +1321,24 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int 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.
@@ -1334,16 +1350,16 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
   {
     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 */
 
@@ -1355,13 +1371,13 @@ int imap_read_headers(struct ImapAccountData *adata, unsigned int msn_begin,
     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 */
 
@@ -1699,11 +1715,12 @@ int imap_cache_del(struct ImapAccountData *adata, struct Email *e)
 {
   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);
 }
 
 /**
@@ -1713,8 +1730,9 @@ int imap_cache_del(struct ImapAccountData *adata, struct Email *e)
  */
 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;
 }
@@ -1823,6 +1841,7 @@ int imap_msg_open(struct Context *ctx, struct Message *msg, int msgno)
   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);
@@ -1837,7 +1856,7 @@ int imap_msg_open(struct Context *ctx, struct Message *msg, int msgno)
   /* 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)
   {
index b6003973da9707d366f13a7b8aecc5de14b645ae..9002a715f90fcd952f4cb0008febd95d98e1f95b 100644 (file)
@@ -82,7 +82,6 @@ void imap_adata_free(void **ptr)
   imap_mboxcache_free(adata);
   mutt_buffer_free(&adata->cmdbuf);
   FREE(&adata->buf);
-  mutt_bcache_close(&adata->bcache);
   FREE(&adata->cmds);
 
   if (adata->conn)
@@ -173,6 +172,8 @@ struct ImapMboxData *imap_mdata_new(struct ImapAccountData *adata, const char *n
   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;
 }
 
@@ -187,9 +188,21 @@ void imap_mdata_free(void **ptr)
 
   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);
 }
 
@@ -301,23 +314,23 @@ void imap_clean_path(char *path, size_t plen)
 /**
  * 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;
@@ -369,25 +382,17 @@ static int imap_hcache_namer(const char *path, char *dest, size_t dlen)
 /**
  * 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;
@@ -404,42 +409,42 @@ header_cache_t *imap_hcache_open(struct ImapAccountData *adata, const char *path
 
 /**
  * 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;
@@ -447,61 +452,61 @@ struct Email *imap_hcache_get(struct ImapAccountData *adata, unsigned int uid)
 
 /**
  * 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;
@@ -509,32 +514,32 @@ int imap_hcache_store_uid_seqset(struct ImapAccountData *adata)
 
 /**
  * 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;
@@ -1034,12 +1039,13 @@ void imap_keepalive(void)
       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);
     }
   }
 }
@@ -1102,11 +1108,11 @@ void imap_allow_reopen(struct Mailbox *m)
   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;
 }
 
 /**
@@ -1118,11 +1124,11 @@ void imap_disallow_reopen(struct Mailbox *m)
   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;
 }
 
 /**