]> granicus.if.org Git - neomutt/commitdiff
imap: handle all mailbox name with ImapMailboxData struct
authorMehdi Abaakouk <sileht@sileht.net>
Wed, 14 Nov 2018 13:13:42 +0000 (14:13 +0100)
committerRichard Russon <rich@flatcap.org>
Thu, 15 Nov 2018 00:26:28 +0000 (00:26 +0000)
imap/browse.c
imap/imap.c
imap/imap_private.h
imap/util.c

index 2d780ca97489da976dfd67d14970c78097254dbb..04ed04a1b24e090d3a109625cc9cf2e6de96395a 100644 (file)
@@ -367,17 +367,18 @@ fail:
 int imap_mailbox_create(const char *path)
 {
   struct ImapAccountData *adata = NULL;
+  struct ImapMailboxData *mdata = NULL;
   char name[LONG_STRING];
   short n;
 
-  adata = imap_adata_find(path, name, sizeof(name), false);
-  if (!adata)
+  if (imap_adata_find(path, &adata, &mdata) < 0)
   {
     mutt_debug(1, "Couldn't find open connection to %s\n", path);
-    return -1;
+    goto err;
   }
 
   /* append a delimiter if necessary */
+  mutt_str_strfcpy(name, mdata->real_name, sizeof(name));
   n = mutt_str_strlen(name);
   if (n && (n < sizeof(name) - 1) && (name[n - 1] != adata->delim))
   {
@@ -386,21 +387,25 @@ int imap_mailbox_create(const char *path)
   }
 
   if (mutt_get_field(_("Create mailbox: "), name, sizeof(name), MUTT_FILE) < 0)
-    return -1;
+    goto err;
 
   if (mutt_str_strlen(name) == 0)
   {
     mutt_error(_("Mailbox must have a name"));
-    return -1;
+    goto err;
   }
 
   if (imap_create_mailbox(adata, name) < 0)
-    return -1;
+    goto err;
 
+  imap_mdata_free((void *) &mdata);
   mutt_message(_("Mailbox created"));
   mutt_sleep(0);
-
   return 0;
+
+err:
+  imap_mdata_free((void *) &mdata);
+  return -1;
 }
 
 /**
@@ -414,45 +419,47 @@ int imap_mailbox_create(const char *path)
 int imap_mailbox_rename(const char *path)
 {
   struct ImapAccountData *adata = NULL;
+  struct ImapMailboxData *mdata = NULL;
   char buf[PATH_MAX];
-  char oldname[LONG_STRING];
   char newname[PATH_MAX];
 
-  adata = imap_adata_find(path, oldname, sizeof(oldname), false);
-  if (!adata)
+  if (imap_adata_find(path, &adata, &mdata) < 0)
   {
     mutt_debug(1, "Couldn't find open connection to %s\n", path);
     return -1;
   }
 
-  if (oldname[0] == '\0')
+  if (mdata->real_name[0] == '\0')
   {
     mutt_error(_("Cannot rename root folder"));
-    return -1;
+    goto err;
   }
 
-  snprintf(buf, sizeof(buf), _("Rename mailbox %s to: "), oldname);
-  mutt_str_strfcpy(newname, oldname, sizeof(newname));
+  snprintf(buf, sizeof(buf), _("Rename mailbox %s to: "), mdata->name);
+  mutt_str_strfcpy(newname, mdata->name, sizeof(newname));
 
   if (mutt_get_field(buf, newname, sizeof(newname), MUTT_FILE) < 0)
-    return -1;
+    goto err;
 
   if (mutt_str_strlen(newname) == 0)
   {
     mutt_error(_("Mailbox must have a name"));
-    return -1;
+    goto err;
   }
 
   imap_fix_path(adata, newname, buf, sizeof(buf));
 
-  if (imap_rename_mailbox(adata, oldname, buf) < 0)
+  if (imap_rename_mailbox(adata, mdata->name, buf) < 0)
   {
     mutt_error(_("Rename failed: %s"), imap_get_qualifier(adata->buf));
-    return -1;
+    goto err;
   }
 
   mutt_message(_("Mailbox renamed"));
   mutt_sleep(0);
-
   return 0;
+
+err:
+  imap_mdata_free((void *) &mdata);
+  return -1;
 }
index 410fca8fa4d68ec51844b99096a3645ebe160c18..fdac8915c100dc42d53801ec1c80ce382f0069b2 100644 (file)
@@ -674,16 +674,15 @@ int imap_create_mailbox(struct ImapAccountData *adata, char *mailbox)
 int imap_access(const char *path)
 {
   struct ImapAccountData *adata = NULL;
-  char mailbox[LONG_STRING];
+  struct ImapMailboxData *mdata = NULL;
+  int rc;
 
-  adata = imap_adata_find(path, mailbox, sizeof(mailbox), true);
-  if (!adata)
+  if (imap_adata_find(path, &adata, &mdata) < 0)
     return -1;
 
-  if (mailbox[0] == '\0')
-    mutt_str_strfcpy(mailbox, "INBOX", sizeof(mailbox));
-
-  return imap_access2(adata, mailbox);
+  rc = imap_access2(adata, mdata->name);
+  imap_mdata_free((void *) &mdata);
+  return rc;
 }
 
 /**
@@ -723,12 +722,15 @@ int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char
  */
 int imap_delete_mailbox(struct Mailbox *m, char *path)
 {
+  struct Url url;
+  char tmp[PATH_MAX];
   char buf[PATH_MAX];
+  char mbox[PATH_MAX];
+  mutt_str_strfcpy(tmp, path, sizeof(tmp));
+  url_parse(&url, tmp);
 
-  struct ImapMailboxData *mdata = imap_mdata_get(m);
-
-  snprintf(buf, sizeof(buf), "DELETE %s", mdata->munge_name);
-
+  imap_munge_mbox_name(m->account->adata, mbox, sizeof(mbox), url.path);
+  snprintf(buf, sizeof(buf), "DELETE %s", mbox);
   if (imap_exec(m->account->adata, buf, 0) != 0)
     return -1;
 
@@ -1419,26 +1421,24 @@ int imap_status(const char *path, bool queue)
   static int queued = 0;
 
   struct ImapAccountData *adata = NULL;
+  struct ImapMailboxData *mdata = NULL;
   char buf[LONG_STRING * 2];
-  char mbox[LONG_STRING];
   struct ImapStatus *status = NULL;
 
-  adata = imap_adata_find(path, buf, sizeof(buf), true);
-  if (!adata)
+  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(buf, adata->mbox_name))
+  if (adata->mailbox && !imap_mxcmp(mdata->name, adata->mbox_name))
     return adata->mailbox->msg_count;
+
   else if (mutt_bit_isset(adata->capabilities, IMAP4REV1) ||
            mutt_bit_isset(adata->capabilities, STATUS))
   {
-    imap_munge_mbox_name(adata, mbox, sizeof(mbox), buf);
-    snprintf(buf, sizeof(buf), "STATUS %s (%s)", mbox, "MESSAGES");
-    imap_unmunge_mbox_name(adata, mbox);
+    snprintf(buf, sizeof(buf), "STATUS %s (%s)", mdata->munge_name, "MESSAGES");
   }
   else
   {
@@ -1457,7 +1457,7 @@ int imap_status(const char *path, bool queue)
     imap_exec(adata, buf, 0);
 
   queued = 0;
-  status = imap_mboxcache_get(adata, mbox, false);
+  status = imap_mboxcache_get(adata, mdata->name, false);
   if (status)
     return status->messages;
 
@@ -1594,14 +1594,14 @@ int imap_search(struct Mailbox *m, const struct Pattern *pat)
 int imap_subscribe(char *path, bool subscribe)
 {
   struct ImapAccountData *adata = NULL;
+  struct ImapMailboxData *mdata = NULL;
   char buf[LONG_STRING * 2];
   char mbox[LONG_STRING];
   char errstr[STRING];
   struct Buffer err, token;
   size_t len = 0;
 
-  adata = imap_adata_find(path, buf, sizeof(buf), false);
-  if (!adata)
+  if (imap_adata_find(path, &adata, &mdata) < 0)
     return -1;
 
   if (ImapCheckSubscribed)
@@ -1618,21 +1618,23 @@ int imap_subscribe(char *path, bool subscribe)
   }
 
   if (subscribe)
-    mutt_message(_("Subscribing to %s..."), buf);
+    mutt_message(_("Subscribing to %s..."), mdata->name);
   else
-    mutt_message(_("Unsubscribing from %s..."), buf);
-  imap_munge_mbox_name(adata, mbox, sizeof(mbox), buf);
+    mutt_message(_("Unsubscribing from %s..."), mdata->name);
 
-  snprintf(buf, sizeof(buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mbox);
+  snprintf(buf, sizeof(buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mdata->munge_name);
 
   if (imap_exec(adata, buf, 0) < 0)
+  {
+    imap_mdata_free((void *) &mdata);
     return -1;
+  }
 
-  imap_unmunge_mbox_name(adata, mbox);
   if (subscribe)
-    mutt_message(_("Subscribed to %s"), mbox);
+    mutt_message(_("Subscribed to %s"), mdata->name);
   else
-    mutt_message(_("Unsubscribed from %s"), mbox);
+    mutt_message(_("Unsubscribed from %s"), mdata->name);
+  imap_mdata_free((void *) &mdata);
   return 0;
 }
 
@@ -1650,9 +1652,8 @@ int imap_subscribe(char *path, bool subscribe)
 int imap_complete(char *buf, size_t buflen, char *path)
 {
   struct ImapAccountData *adata = NULL;
-  char list[LONG_STRING];
+  struct ImapMailboxData *mdata = NULL;
   char tmp[LONG_STRING * 2];
-  char mailbox[LONG_STRING];
   struct ImapList listresp;
   char completion[LONG_STRING];
   int clen;
@@ -1660,27 +1661,22 @@ int imap_complete(char *buf, size_t buflen, char *path)
   int completions = 0;
   int rc;
 
-  adata = imap_adata_find(path, mailbox, sizeof(mailbox), false);
-  if (!adata)
+  if (imap_adata_find(path, &adata, &mdata) < 0)
   {
     mutt_str_strfcpy(buf, path, buflen);
     return complete_hosts(buf, buflen);
   }
 
-  /* reformat path for IMAP list, and append wildcard */
-  /* don't use INBOX in place of "" */
-  if (mailbox[0] != '\0')
-    imap_fix_path(adata, mailbox, list, sizeof(list));
-  else
-    list[0] = '\0';
-
   /* fire off command */
-  snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"", ImapListSubscribed ? "LSUB" : "LIST", list);
+  snprintf(tmp, sizeof(tmp), "%s \"\" \"%s%%\"",
+           ImapListSubscribed ? "LSUB" : "LIST", mdata->real_name);
 
   imap_cmd_start(adata, tmp);
 
   /* and see what the results are */
-  mutt_str_strfcpy(completion, mailbox, sizeof(completion));
+  mutt_str_strfcpy(completion, mdata->name, sizeof(completion));
+  imap_mdata_free((void *) &mdata);
+
   adata->cmdtype = IMAP_CT_LIST;
   adata->cmddata = &listresp;
   do
@@ -1734,27 +1730,28 @@ int imap_complete(char *buf, size_t buflen, char *path)
  */
 int imap_fast_trash(struct Mailbox *m, char *dest)
 {
-  char mbox[LONG_STRING];
-  char mmbox[LONG_STRING];
   char prompt[LONG_STRING];
-  int rc;
+  int rc = -1;
   bool triedcreate = false;
   struct Buffer *sync_cmd = NULL;
   int err_continue = MUTT_NO;
 
   struct ImapAccountData *adata = imap_adata_get(m);
-  struct ImapAccountData *dest_adata = imap_adata_find(dest, mbox, sizeof(mbox), true);
+  struct ImapAccountData *dest_adata = NULL;
+  struct ImapMailboxData *dest_mdata = NULL;
+
+  if (imap_adata_find(dest, &dest_adata, &dest_mdata) < 0)
+    return -1;
+
+  sync_cmd = mutt_buffer_new();
 
   /* check that the save-to folder is in the same account */
   if (!mutt_account_match(&(adata->conn->account), &(dest_adata->conn->account)))
   {
     mutt_debug(3, "%s not same server as %s\n", dest, m->path);
-    return 1;
+    goto out;
   }
 
-  imap_munge_mbox_name(adata, mmbox, sizeof(mmbox), mbox);
-
-  sync_cmd = mutt_buffer_new();
   for (int i = 0; i < m->msg_count; i++)
   {
     if (m->hdrs[i]->active && m->hdrs[i]->changed && m->hdrs[i]->deleted &&
@@ -1772,7 +1769,7 @@ int imap_fast_trash(struct Mailbox *m, char *dest)
   /* loop in case of TRYCREATE */
   do
   {
-    rc = imap_exec_msgset(adata, "UID COPY", mmbox, MUTT_TRASH, false, false);
+    rc = imap_exec_msgset(adata, "UID COPY", dest_mdata->munge_name, MUTT_TRASH, false, false);
     if (!rc)
     {
       mutt_debug(1, "No messages to trash\n");
@@ -1787,7 +1784,7 @@ int imap_fast_trash(struct Mailbox *m, char *dest)
     else
     {
       mutt_message(ngettext("Copying %d message to %s...", "Copying %d messages to %s...", rc),
-                   rc, mbox);
+                   rc, dest_mdata->name);
     }
 
     /* let's get it on */
@@ -1796,20 +1793,20 @@ int imap_fast_trash(struct Mailbox *m, char *dest)
     {
       if (triedcreate)
       {
-        mutt_debug(1, "Already tried to create mailbox %s\n", mbox);
+        mutt_debug(1, "Already tried to create mailbox %s\n", dest_mdata->name);
         break;
       }
       /* bail out if command failed for reasons other than nonexistent target */
       if (!mutt_str_startswith(imap_get_qualifier(adata->buf), "[TRYCREATE]", CASE_IGNORE))
         break;
       mutt_debug(3, "server suggests TRYCREATE\n");
-      snprintf(prompt, sizeof(prompt), _("Create %s?"), mbox);
+      snprintf(prompt, sizeof(prompt), _("Create %s?"), dest_mdata->name);
       if (Confirmcreate && mutt_yesorno(prompt, 1) != MUTT_YES)
       {
         mutt_clear_error();
         goto out;
       }
-      if (imap_create_mailbox(adata, mbox) < 0)
+      if (imap_create_mailbox(adata, dest_mdata->name) < 0)
         break;
       triedcreate = true;
     }
@@ -1825,6 +1822,7 @@ int imap_fast_trash(struct Mailbox *m, char *dest)
 
 out:
   mutt_buffer_free(&sync_cmd);
+  imap_mdata_free((void *) &dest_mdata);
 
   return (rc < 0) ? -1 : rc;
 }
index 9a61329a63646e92849a5a8c3a63efb8fc040e63..1e7377351841a2d2b15addb549be037d3d8823b9 100644 (file)
@@ -317,7 +317,7 @@ int imap_login(struct ImapAccountData *adata);
 void imap_logout(struct ImapAccountData **adata);
 int imap_sync_message_for_copy(struct ImapAccountData *adata, struct Email *e, struct Buffer *cmd, int *err_continue);
 bool imap_has_flag(struct ListHead *flag_list, const char *flag);
-struct ImapAccountData *imap_adata_find(const char *path, char *mailbox, size_t mailboxlen, bool fix_path);
+int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMailboxData **mdata);
 
 /* auth.c */
 int imap_authenticate(struct ImapAccountData *adata);
index 990b6c3e0887b214e86a22df5182544c0516cf9c..ff90efe8d04c9177db73de4e052d8f358aff2a57 100644 (file)
@@ -126,37 +126,32 @@ struct ImapAccountData *imap_adata_get(struct Mailbox *m)
 /**
  * imap_adata_find - Find the Account data for this path
  */
-struct ImapAccountData *imap_adata_find(const char *path, char *mailbox,
-                                        size_t mailboxlen, bool fix_path)
+int imap_adata_find(const char *path, struct ImapAccountData **adata,
+                    struct ImapMailboxData **mdata)
 {
   struct ConnAccount conn_account;
+  struct ImapAccountData *tmp_adata;
   char tmp[LONG_STRING];
 
   if (imap_parse_path2(path, &conn_account, tmp, sizeof(tmp)) < 0)
-    return NULL;
+    return -1;
 
   struct Account *np = NULL;
-  struct ImapAccountData *adata = NULL;
   TAILQ_FOREACH(np, &AllAccounts, entries)
   {
     if (np->magic != MUTT_IMAP)
       continue;
 
-    adata = np->adata;
-    if (imap_account_match(&adata->conn_account, &conn_account))
+    tmp_adata = np->adata;
+    if (imap_account_match(&tmp_adata->conn_account, &conn_account))
     {
-      if (tmp[0] != '\0')
-      {
-        if (fix_path)
-          imap_fix_path(adata, tmp, mailbox, mailboxlen);
-        else
-          mutt_str_strfcpy(mailbox, tmp, mailboxlen);
-      }
-      return adata;
+      *mdata = imap_mdata_new(tmp_adata, tmp);
+      *adata = tmp_adata;
+      return 0;
     }
   }
   mutt_debug(3, "no ImapAccountData found\n");
-  return NULL;
+  return -1;
 }
 
 /**
@@ -264,20 +259,21 @@ void imap_get_parent(const char *mbox, char delim, char *buf, size_t buflen)
 void imap_get_parent_path(const char *path, char *buf, size_t buflen)
 {
   struct ImapAccountData *adata = NULL;
-  char mbox[LONG_STRING], tmp[LONG_STRING];
+  struct ImapMailboxData *mdata = NULL;
+  char mbox[LONG_STRING];
 
-  adata = imap_adata_find(path, tmp, sizeof(tmp), true);
-  if (!adata || tmp[0] == '\0')
+  if (imap_adata_find(path, &adata, &mdata) < 0)
   {
     mutt_str_strfcpy(buf, path, buflen);
     return;
   }
 
   /* Gets the parent mbox in mbox */
-  imap_get_parent(mbox, adata->delim, mbox, sizeof(mbox));
+  imap_get_parent(mdata->name, adata->delim, mbox, sizeof(mbox));
 
   /* Returns a fully qualified IMAP url */
   imap_qualify_path2(buf, buflen, &adata->conn_account, mbox);
+  imap_mdata_free((void *) &mdata);
 }
 
 /**
@@ -290,14 +286,15 @@ void imap_get_parent_path(const char *path, char *buf, size_t buflen)
 void imap_clean_path(char *path, size_t plen)
 {
   struct ImapAccountData *adata = NULL;
-  char mbox[LONG_STRING], tmp[LONG_STRING];
+  struct ImapMailboxData *mdata = NULL;
 
-  adata = imap_adata_find(path, tmp, sizeof(tmp), true);
-  if (!adata || tmp[0] == '\0')
+  if (imap_adata_find(path, &adata, &mdata) < 0)
     return;
 
   /* Returns a fully qualified IMAP url */
-  imap_qualify_path2(path, plen, &adata->conn_account, mbox);
+  // TODO(sileht): Put it in mdata directly ?
+  imap_qualify_path2(path, plen, &adata->conn_account, mdata->name);
+  imap_mdata_free((void *) &mdata);
 }
 
 #ifdef USE_HCACHE