NeoMutt  2023-05-17-56-ga67199
Teaching an old dog new tricks
DOXYGEN
browse.c File Reference

GUI select an IMAP mailbox from a list. More...

#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "private.h"
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "conn/lib.h"
#include "mutt.h"
#include "lib.h"
#include "browser/lib.h"
#include "enter/lib.h"
#include "adata.h"
#include "mdata.h"
#include "mutt_logging.h"
#include "muttlib.h"
+ Include dependency graph for browse.c:

Go to the source code of this file.

Functions

static void add_folder (char delim, char *folder, bool noselect, bool noinferiors, struct BrowserState *state, bool isparent)
 Format and add an IMAP folder to the browser. More...
 
static int browse_add_list_result (struct ImapAccountData *adata, const char *cmd, struct BrowserState *bstate, bool isparent)
 Add entries to the folder browser. More...
 
int imap_browse (const char *path, struct BrowserState *state)
 IMAP hook into the folder browser. More...
 
int imap_mailbox_create (const char *path)
 Create a new IMAP mailbox. More...
 
int imap_mailbox_rename (const char *path)
 Rename a mailbox. More...
 

Detailed Description

GUI select an IMAP mailbox from a list.

Authors
  • Brandon Long
  • Brendan Cully

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file browse.c.

Function Documentation

◆ add_folder()

static void add_folder ( char  delim,
char *  folder,
bool  noselect,
bool  noinferiors,
struct BrowserState state,
bool  isparent 
)
static

Format and add an IMAP folder to the browser.

Parameters
delimPath delimiter
folderName of the folder
noselecttrue if item isn't selectable
noinferiorstrue if item has no children
stateBrowser state to add to
isparenttrue if item represents the parent folder

The folder parameter should already be 'unmunged' via imap_unmunge_mbox_name().

Definition at line 62 of file browse.c.

64{
65 char tmp[PATH_MAX] = { 0 };
66 char relpath[PATH_MAX] = { 0 };
67 struct ConnAccount cac = { { 0 } };
68 char mailbox[1024] = { 0 };
69 struct FolderFile ff = { 0 };
70
71 if (imap_parse_path(state->folder, &cac, mailbox, sizeof(mailbox)))
72 return;
73
74 if (isparent)
75 {
76 /* render superiors as unix-standard ".." */
77 mutt_str_copy(relpath, "../", sizeof(relpath));
78 }
79 else if (mutt_str_startswith(folder, mailbox))
80 {
81 /* strip current folder from target, to render a relative path */
82 mutt_str_copy(relpath, folder + mutt_str_len(mailbox), sizeof(relpath));
83 }
84 else
85 {
86 mutt_str_copy(relpath, folder, sizeof(relpath));
87 }
88
89 /* apply filemask filter. This should really be done at menu setup rather
90 * than at scan, since it's so expensive to scan. But that's big changes
91 * to browser.c */
92 const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
93 if (!mutt_regex_match(c_mask, relpath))
94 {
95 return;
96 }
97
98 imap_qualify_path(tmp, sizeof(tmp), &cac, folder);
99 ff.name = mutt_str_dup(tmp);
100
101 /* mark desc with delim in browser if it can have subfolders */
102 if (!isparent && !noinferiors && (strlen(relpath) < sizeof(relpath) - 1))
103 {
104 relpath[strlen(relpath) + 1] = '\0';
105 relpath[strlen(relpath)] = delim;
106 }
107
108 ff.desc = mutt_str_dup(relpath);
109 ff.imap = true;
110
111 /* delimiter at the root is useless. */
112 if (folder[0] == '\0')
113 delim = '\0';
114 ff.delim = delim;
115 ff.selectable = !noselect;
116 ff.inferiors = !noinferiors;
117
118 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
120 struct MailboxNode *np = NULL;
121 STAILQ_FOREACH(np, &ml, entries)
122 {
123 if (mutt_str_equal(tmp, mailbox_path(np->mailbox)))
124 break;
125 }
126
127 if (np)
128 {
129 ff.has_mailbox = true;
130 ff.has_new_mail = np->mailbox->has_new;
131 ff.msg_count = np->mailbox->msg_count;
132 ff.msg_unread = np->mailbox->msg_unread;
133 }
135
136 ARRAY_ADD(&state->entry, ff);
137}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition: array.h:155
const struct Regex * cs_subset_regex(const struct ConfigSubset *sub, const char *name)
Get a regex config item by name.
Definition: helpers.c:243
int imap_parse_path(const char *path, struct ConnAccount *cac, char *mailbox, size_t mailboxlen)
Parse an IMAP mailbox name into ConnAccount, name.
Definition: util.c:473
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:815
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:209
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition: mailbox.h:42
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:635
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:251
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:228
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:568
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
#define PATH_MAX
Definition: mutt.h:41
void neomutt_mailboxlist_clear(struct MailboxList *ml)
Free a Mailbox List.
Definition: neomutt.c:141
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:164
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
char * folder
Folder name.
Definition: lib.h:115
struct BrowserStateEntry entry
Array of files / dirs / mailboxes.
Definition: lib.h:112
Login details for a remote server.
Definition: connaccount.h:53
Browser entry representing a folder/dir.
Definition: lib.h:73
bool selectable
Folder can be selected.
Definition: lib.h:92
char delim
Path delimiter.
Definition: lib.h:89
bool imap
This is an IMAP folder.
Definition: lib.h:91
bool has_mailbox
This is a mailbox.
Definition: lib.h:95
char * name
Name of file/dir/mailbox.
Definition: lib.h:81
bool has_new_mail
true if mailbox has "new mail"
Definition: lib.h:84
char * desc
Description of mailbox.
Definition: lib.h:82
int msg_count
total number of messages
Definition: lib.h:85
bool inferiors
Folder has children.
Definition: lib.h:93
int msg_unread
number of unread messages
Definition: lib.h:86
List of Mailboxes.
Definition: mailbox.h:152
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:153
bool has_new
Mailbox has new mail.
Definition: mailbox.h:85
int msg_count
Total number of messages.
Definition: mailbox.h:88
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
Cached regular expression.
Definition: regex3.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ browse_add_list_result()

static int browse_add_list_result ( struct ImapAccountData adata,
const char *  cmd,
struct BrowserState bstate,
bool  isparent 
)
static

Add entries to the folder browser.

Parameters
adataImap Account data
cmdCommand string from server
bstateBrowser state to add to
isparentIs this a shortcut for the parent directory?
Return values
0Success
-1Failure

Definition at line 148 of file browse.c.

150{
151 struct ImapList list = { 0 };
152 int rc;
153 struct Url *url = url_parse(bstate->folder);
154 if (!url)
155 return -1;
156
157 imap_cmd_start(adata, cmd);
158 adata->cmdresult = &list;
159 do
160 {
161 list.name = NULL;
162 rc = imap_cmd_step(adata);
163
164 if ((rc == IMAP_RES_CONTINUE) && list.name)
165 {
166 /* Let a parent folder never be selectable for navigation */
167 if (isparent)
168 list.noselect = true;
169 /* prune current folder from output */
170 if (isparent || !mutt_str_startswith(url->path, list.name))
171 add_folder(list.delim, list.name, list.noselect, list.noinferiors, bstate, isparent);
172 }
173 } while (rc == IMAP_RES_CONTINUE);
174 adata->cmdresult = NULL;
175
176 url_free(&url);
177
178 return (rc == IMAP_RES_OK) ? 0 : -1;
179}
static void add_folder(char delim, char *folder, bool noselect, bool noinferiors, struct BrowserState *state, bool isparent)
Format and add an IMAP folder to the browser.
Definition: browse.c:62
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1095
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1109
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:55
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:56
struct ImapList * cmdresult
Definition: adata.h:66
Items in an IMAP browser.
Definition: private.h:149
bool noselect
Definition: private.h:152
bool noinferiors
Definition: private.h:153
char * name
Definition: private.h:150
char delim
Definition: private.h:151
A parsed URL proto://user:password@host:port/path?a=1&b=2
Definition: url.h:69
char * path
Path.
Definition: url.h:75
struct Url * url_parse(const char *src)
Fill in Url.
Definition: url.c:238
void url_free(struct Url **ptr)
Free the contents of a URL.
Definition: url.c:123
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_browse()

int imap_browse ( const char *  path,
struct BrowserState state 
)

IMAP hook into the folder browser.

Parameters
pathCurrent folder
stateBrowserState to populate
Return values
0Success
-1Failure

Fill out browser_state, given a current folder to browse

Definition at line 190 of file browse.c.

191{
192 struct ImapAccountData *adata = NULL;
193 struct ImapList list = { 0 };
194 struct ConnAccount cac = { { 0 } };
195 char buf[PATH_MAX + 16];
196 char mbox[PATH_MAX] = { 0 };
197 char munged_mbox[PATH_MAX] = { 0 };
198 const char *list_cmd = NULL;
199 int len;
200 int n;
201 char ctmp;
202 bool showparents = false;
203
204 if (imap_parse_path(path, &cac, buf, sizeof(buf)))
205 {
206 mutt_error(_("%s is an invalid IMAP path"), path);
207 return -1;
208 }
209
210 const bool c_imap_check_subscribed = cs_subset_bool(NeoMutt->sub, "imap_check_subscribed");
211 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed", false, NULL);
212
213 // Pick first mailbox connected to the same server
214 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
216 struct MailboxNode *np = NULL;
217 STAILQ_FOREACH(np, &ml, entries)
218 {
219 adata = imap_adata_get(np->mailbox);
220 // Pick first mailbox connected on the same server
221 if (imap_account_match(&adata->conn->account, &cac))
222 break;
223 adata = NULL;
224 }
226 if (!adata)
227 goto fail;
228
229 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
230 if (c_imap_list_subscribed)
231 {
232 /* RFC3348 section 3 states LSUB is unreliable for hierarchy information.
233 * The newer LIST extensions are designed for this. */
235 list_cmd = "LIST (SUBSCRIBED RECURSIVEMATCH)";
236 else
237 list_cmd = "LSUB";
238 }
239 else
240 {
241 list_cmd = "LIST";
242 }
243
244 mutt_message(_("Getting folder list..."));
245
246 /* skip check for parents when at the root */
247 if (buf[0] == '\0')
248 {
249 mbox[0] = '\0';
250 n = 0;
251 }
252 else
253 {
254 imap_fix_path(adata->delim, buf, mbox, sizeof(mbox));
255 n = mutt_str_len(mbox);
256 }
257
258 if (n)
259 {
260 int rc;
261 mutt_debug(LL_DEBUG3, "mbox: %s\n", mbox);
262
263 /* if our target exists and has inferiors, enter it if we
264 * aren't already going to */
265 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), mbox);
266 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
268 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
269 imap_cmd_start(adata, buf);
270 adata->cmdresult = &list;
271 do
272 {
273 list.name = 0;
274 rc = imap_cmd_step(adata);
275 if ((rc == IMAP_RES_CONTINUE) && list.name)
276 {
277 if (!list.noinferiors && list.name[0] &&
278 (imap_mxcmp(list.name, mbox) == 0) && (n < sizeof(mbox) - 1))
279 {
280 mbox[n++] = list.delim;
281 mbox[n] = '\0';
282 }
283 }
284 } while (rc == IMAP_RES_CONTINUE);
285 adata->cmdresult = NULL;
286
287 /* if we're descending a folder, mark it as current in browser_state */
288 if (mbox[n - 1] == list.delim)
289 {
290 showparents = true;
291 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
292 state->folder = mutt_str_dup(buf);
293 n--;
294 }
295
296 /* Find superiors to list
297 * Note: UW-IMAP servers return folder + delimiter when asked to list
298 * folder + delimiter. Cyrus servers don't. So we ask for folder,
299 * and tack on delimiter ourselves.
300 * Further note: UW-IMAP servers return nothing when asked for
301 * NAMESPACES without delimiters at the end. Argh! */
302 for (n--; n >= 0 && mbox[n] != list.delim; n--)
303 ; // do nothing
304
305 if (n > 0) /* "aaaa/bbbb/" -> "aaaa" */
306 {
307 /* forget the check, it is too delicate (see above). Have we ever
308 * had the parent not exist? */
309 ctmp = mbox[n];
310 mbox[n] = '\0';
311
312 if (showparents)
313 {
314 mutt_debug(LL_DEBUG3, "adding parent %s\n", mbox);
315 add_folder(list.delim, mbox, true, false, state, true);
316 }
317
318 /* if our target isn't a folder, we are in our superior */
319 if (!state->folder)
320 {
321 /* store folder with delimiter */
322 mbox[n++] = ctmp;
323 ctmp = mbox[n];
324 mbox[n] = '\0';
325 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
326 state->folder = mutt_str_dup(buf);
327 }
328 mbox[n] = ctmp;
329 }
330 else
331 {
332 /* "/bbbb/" -> add "/", "aaaa/" -> add "" */
333 char relpath[2] = { 0 };
334 /* folder may be "/" */
335 snprintf(relpath, sizeof(relpath), "%c", (n < 0) ? '\0' : adata->delim);
336 if (showparents)
337 add_folder(adata->delim, relpath, true, false, state, true);
338 if (!state->folder)
339 {
340 imap_qualify_path(buf, sizeof(buf), &cac, relpath);
341 state->folder = mutt_str_dup(buf);
342 }
343 }
344 }
345
346 /* no namespace, no folder: set folder to host only */
347 if (!state->folder)
348 {
349 imap_qualify_path(buf, sizeof(buf), &cac, NULL);
350 state->folder = mutt_str_dup(buf);
351 }
352
353 mutt_debug(LL_DEBUG3, "Quoting mailbox scan: %s -> ", mbox);
354 snprintf(buf, sizeof(buf), "%s%%", mbox);
355 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), buf);
356 mutt_debug(LL_DEBUG3, "%s\n", munged_mbox);
357 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
359 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
360 if (browse_add_list_result(adata, buf, state, false))
361 goto fail;
362
363 if (ARRAY_EMPTY(&state->entry))
364 {
365 // L10N: (%s) is the name / path of the folder we were trying to browse
366 mutt_error(_("No such folder: %s"), path);
367 goto fail;
368 }
369
371
372 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed",
373 c_imap_check_subscribed, NULL);
374 return 0;
375
376fail:
377 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed",
378 c_imap_check_subscribed, NULL);
379 return -1;
380}
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:73
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
#define mutt_error(...)
Definition: logging2.h:90
#define mutt_message(...)
Definition: logging2.h:89
#define mutt_debug(LEVEL,...)
Definition: logging2.h:87
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:90
static int browse_add_list_result(struct ImapAccountData *adata, const char *cmd, struct BrowserState *bstate, bool isparent)
Add entries to the folder browser.
Definition: browse.c:148
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:544
char * imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition: util.c:678
#define IMAP_CAP_LIST_EXTENDED
RFC5258: IMAP4 LIST Command Extensions.
Definition: private.h:138
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1039
void imap_munge_mbox_name(bool unicode, char *dest, size_t dlen, const char *src)
Quote awkward characters in a mailbox name.
Definition: util.c:906
@ LL_DEBUG3
Log at debug level 3.
Definition: logging2.h:45
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
#define _(a)
Definition: message.h:28
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void * adata
Private data (for Mailbox backends)
Definition: account.h:43
struct ConnAccount account
Account details: username, password, etc.
Definition: connection.h:50
IMAP-specific Account data -.
Definition: adata.h:40
char delim
Path delimiter.
Definition: adata.h:75
bool unicode
If true, we can send UTF-8, and the server will use UTF8 rather than mUTF7.
Definition: adata.h:62
ImapCapFlags capabilities
Capability flags.
Definition: adata.h:55
struct Connection * conn
Connection to IMAP server.
Definition: adata.h:41
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:310
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mailbox_create()

int imap_mailbox_create ( const char *  path)

Create a new IMAP mailbox.

Parameters
pathMailbox to create
Return values
0Success
-1Failure

Prompt for a new mailbox name, and try to create it

Definition at line 390 of file browse.c.

391{
392 struct ImapAccountData *adata = NULL;
393 struct ImapMboxData *mdata = NULL;
394 struct Buffer *name = buf_pool_get();
395 int rc = -1;
396
397 if (imap_adata_find(path, &adata, &mdata) < 0)
398 {
399 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
400 goto done;
401 }
402
403 /* append a delimiter if necessary */
404 const size_t n = buf_strcpy(name, mdata->real_name);
405 if ((n != 0) && (name->data[n - 1] != adata->delim))
406 {
407 buf_addch(name, adata->delim);
408 }
409
410 if (buf_get_field(_("Create mailbox: "), name, MUTT_COMP_FILE, false, NULL, NULL, NULL) != 0)
411 {
412 goto done;
413 }
414
415 if (buf_is_empty(name))
416 {
417 mutt_error(_("Mailbox must have a name"));
418 goto done;
419 }
420
421 if (imap_create_mailbox(adata, buf_string(name)) < 0)
422 goto done;
423
424 imap_mdata_free((void *) &mdata);
425 mutt_message(_("Mailbox created"));
426 mutt_sleep(0);
427 rc = 0;
428
429done:
430 imap_mdata_free((void *) &mdata);
431 buf_pool_release(&name);
432 return rc;
433}
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:303
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:401
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:90
int buf_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: mdata.c:40
int imap_adata_find(const char *path, struct ImapAccountData **adata, struct ImapMboxData **mdata)
Find the Account data for this path.
Definition: util.c:71
int imap_create_mailbox(struct ImapAccountData *adata, const char *mailbox)
Create a new mailbox.
Definition: imap.c:428
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:58
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1424
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
String manipulation buffer.
Definition: buffer.h:34
char * data
Pointer to data.
Definition: buffer.h:35
IMAP-specific Mailbox data -.
Definition: mdata.h:39
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition: mdata.h:42
void * mdata
Driver specific data.
Definition: mailbox.h:132
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ imap_mailbox_rename()

int imap_mailbox_rename ( const char *  path)

Rename a mailbox.

Parameters
pathMailbox to rename
Return values
0Success
-1Failure

The user will be prompted for a new name.

Definition at line 443 of file browse.c.

444{
445 struct ImapAccountData *adata = NULL;
446 struct ImapMboxData *mdata = NULL;
447 struct Buffer *buf = NULL;
448 struct Buffer *newname = NULL;
449 int rc = -1;
450
451 if (imap_adata_find(path, &adata, &mdata) < 0)
452 {
453 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
454 goto done;
455 }
456
457 if (mdata->real_name[0] == '\0')
458 {
459 mutt_error(_("Can't rename root folder"));
460 goto done;
461 }
462
463 buf = buf_pool_get();
464 newname = buf_pool_get();
465
466 buf_printf(buf, _("Rename mailbox %s to: "), mdata->name);
467 buf_strcpy(newname, mdata->name);
468
469 if (buf_get_field(buf_string(buf), newname, MUTT_COMP_FILE, false, NULL, NULL, NULL) != 0)
470 {
471 goto done;
472 }
473
474 if (buf_is_empty(newname))
475 {
476 mutt_error(_("Mailbox must have a name"));
477 goto done;
478 }
479
480 imap_fix_path(adata->delim, buf_string(newname), buf->data, buf->dsize);
481
482 if (imap_rename_mailbox(adata, mdata->name, buf_string(buf)) < 0)
483 {
484 mutt_error(_("Rename failed: %s"), imap_get_qualifier(adata->buf));
485 goto done;
486 }
487
488 mutt_message(_("Mailbox renamed"));
489 mutt_sleep(0);
490 rc = 0;
491
492done:
493 imap_mdata_free((void *) &mdata);
494 buf_pool_release(&buf);
495 buf_pool_release(&newname);
496
497 return rc;
498}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:767
int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char *newname)
Rename a mailbox.
Definition: imap.c:469
size_t dsize
Length of data.
Definition: buffer.h:37
char * buf
Definition: adata.h:59
char * name
Mailbox name.
Definition: mdata.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function: