From 20f567b326613ed74b0481f144c74790ac4ac88b Mon Sep 17 00:00:00 2001 From: Mehdi Abaakouk Date: Wed, 14 Nov 2018 14:13:42 +0100 Subject: [PATCH] imap: handle all mailbox name with ImapMailboxData struct --- imap/browse.c | 45 +++++++++++-------- imap/imap.c | 106 ++++++++++++++++++++++---------------------- imap/imap_private.h | 2 +- imap/util.c | 43 +++++++++--------- 4 files changed, 99 insertions(+), 97 deletions(-) diff --git a/imap/browse.c b/imap/browse.c index 2d780ca97..04ed04a1b 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -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; } diff --git a/imap/imap.c b/imap/imap.c index 410fca8fa..fdac8915c 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -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; } diff --git a/imap/imap_private.h b/imap/imap_private.h index 9a61329a6..1e7377351 100644 --- a/imap/imap_private.h +++ b/imap/imap_private.h @@ -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); diff --git a/imap/util.c b/imap/util.c index 990b6c3e0..ff90efe8d 100644 --- a/imap/util.c +++ b/imap/util.c @@ -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 -- 2.40.0