NeoMutt  2022-04-29-249-gaae397
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 *state, 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 /* render superiors as unix-standard ".." */
75 if (isparent)
76 mutt_str_copy(relpath, "../", sizeof(relpath));
77 /* strip current folder from target, to render a relative path */
78 else if (mutt_str_startswith(folder, mailbox))
79 mutt_str_copy(relpath, folder + mutt_str_len(mailbox), sizeof(relpath));
80 else
81 mutt_str_copy(relpath, folder, sizeof(relpath));
82
83 /* apply filemask filter. This should really be done at menu setup rather
84 * than at scan, since it's so expensive to scan. But that's big changes
85 * to browser.c */
86 const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
87 if (!mutt_regex_match(c_mask, relpath))
88 {
89 return;
90 }
91
92 imap_qualify_path(tmp, sizeof(tmp), &cac, folder);
93 ff.name = mutt_str_dup(tmp);
94
95 /* mark desc with delim in browser if it can have subfolders */
96 if (!isparent && !noinferiors && (strlen(relpath) < sizeof(relpath) - 1))
97 {
98 relpath[strlen(relpath) + 1] = '\0';
99 relpath[strlen(relpath)] = delim;
100 }
101
102 ff.desc = mutt_str_dup(relpath);
103 ff.imap = true;
104
105 /* delimiter at the root is useless. */
106 if (folder[0] == '\0')
107 delim = '\0';
108 ff.delim = delim;
109 ff.selectable = !noselect;
110 ff.inferiors = !noinferiors;
111
112 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
114 struct MailboxNode *np = NULL;
115 STAILQ_FOREACH(np, &ml, entries)
116 {
117 if (mutt_str_equal(tmp, mailbox_path(np->mailbox)))
118 break;
119 }
120
121 if (np)
122 {
123 ff.has_mailbox = true;
124 ff.has_new_mail = np->mailbox->has_new;
125 ff.msg_count = np->mailbox->msg_count;
126 ff.msg_unread = np->mailbox->msg_unread;
127 }
129
130 ARRAY_ADD(&state->entry, ff);
131}
#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:482
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:820
static const char * mailbox_path(const struct Mailbox *m)
Get the Mailbox's path string.
Definition: mailbox.h:210
@ 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:631
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:250
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:807
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
Definition: string.c:227
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:567
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:652
#define PATH_MAX
Definition: mutt.h:40
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:153
struct Mailbox * mailbox
Mailbox in the list.
Definition: mailbox.h:154
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 state,
bool  isparent 
)
static

Add entries to the folder browser.

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

Definition at line 142 of file browse.c.

144{
145 struct ImapList list = { 0 };
146 int rc;
147 struct Url *url = url_parse(state->folder);
148
149 imap_cmd_start(adata, cmd);
150 adata->cmdresult = &list;
151 do
152 {
153 list.name = NULL;
154 rc = imap_cmd_step(adata);
155
156 if ((rc == IMAP_RES_CONTINUE) && list.name)
157 {
158 /* Let a parent folder never be selectable for navigation */
159 if (isparent)
160 list.noselect = true;
161 /* prune current folder from output */
162 if (isparent || !mutt_str_startswith(url->path, list.name))
163 add_folder(list.delim, list.name, list.noselect, list.noinferiors, state, isparent);
164 }
165 } while (rc == IMAP_RES_CONTINUE);
166 adata->cmdresult = NULL;
167
168 url_free(&url);
169
170 return (rc == IMAP_RES_OK) ? 0 : -1;
171}
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:1062
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1076
#define IMAP_RES_OK
<tag> OK ...
Definition: private.h:56
#define IMAP_RES_CONTINUE
* ...
Definition: private.h:57
struct ImapList * cmdresult
Definition: adata.h:66
Items in an IMAP browser.
Definition: private.h:150
bool noselect
Definition: private.h:153
bool noinferiors
Definition: private.h:154
char * name
Definition: private.h:151
char delim
Definition: private.h:152
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:234
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 182 of file browse.c.

183{
184 struct ImapAccountData *adata = NULL;
185 struct ImapList list = { 0 };
186 struct ConnAccount cac = { { 0 } };
187 char buf[PATH_MAX + 16];
188 char mbox[PATH_MAX] = { 0 };
189 char munged_mbox[PATH_MAX] = { 0 };
190 const char *list_cmd = NULL;
191 int len;
192 int n;
193 char ctmp;
194 bool showparents = false;
195
196 if (imap_parse_path(path, &cac, buf, sizeof(buf)))
197 {
198 mutt_error(_("%s is an invalid IMAP path"), path);
199 return -1;
200 }
201
202 const bool c_imap_check_subscribed = cs_subset_bool(NeoMutt->sub, "imap_check_subscribed");
203 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed", false, NULL);
204
205 // Pick first mailbox connected to the same server
206 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
208 struct MailboxNode *np = NULL;
209 STAILQ_FOREACH(np, &ml, entries)
210 {
211 adata = imap_adata_get(np->mailbox);
212 // Pick first mailbox connected on the same server
213 if (imap_account_match(&adata->conn->account, &cac))
214 break;
215 adata = NULL;
216 }
218 if (!adata)
219 goto fail;
220
221 const bool c_imap_list_subscribed = cs_subset_bool(NeoMutt->sub, "imap_list_subscribed");
222 if (c_imap_list_subscribed)
223 {
224 /* RFC3348 section 3 states LSUB is unreliable for hierarchy information.
225 * The newer LIST extensions are designed for this. */
227 list_cmd = "LIST (SUBSCRIBED RECURSIVEMATCH)";
228 else
229 list_cmd = "LSUB";
230 }
231 else
232 {
233 list_cmd = "LIST";
234 }
235
236 mutt_message(_("Getting folder list..."));
237
238 /* skip check for parents when at the root */
239 if (buf[0] == '\0')
240 {
241 mbox[0] = '\0';
242 n = 0;
243 }
244 else
245 {
246 imap_fix_path(adata->delim, buf, mbox, sizeof(mbox));
247 n = mutt_str_len(mbox);
248 }
249
250 if (n)
251 {
252 int rc;
253 mutt_debug(LL_DEBUG3, "mbox: %s\n", mbox);
254
255 /* if our target exists and has inferiors, enter it if we
256 * aren't already going to */
257 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), mbox);
258 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
260 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
261 imap_cmd_start(adata, buf);
262 adata->cmdresult = &list;
263 do
264 {
265 list.name = 0;
266 rc = imap_cmd_step(adata);
267 if ((rc == IMAP_RES_CONTINUE) && list.name)
268 {
269 if (!list.noinferiors && list.name[0] &&
270 (imap_mxcmp(list.name, mbox) == 0) && (n < sizeof(mbox) - 1))
271 {
272 mbox[n++] = list.delim;
273 mbox[n] = '\0';
274 }
275 }
276 } while (rc == IMAP_RES_CONTINUE);
277 adata->cmdresult = NULL;
278
279 /* if we're descending a folder, mark it as current in browser_state */
280 if (mbox[n - 1] == list.delim)
281 {
282 showparents = true;
283 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
284 state->folder = mutt_str_dup(buf);
285 n--;
286 }
287
288 /* Find superiors to list
289 * Note: UW-IMAP servers return folder + delimiter when asked to list
290 * folder + delimiter. Cyrus servers don't. So we ask for folder,
291 * and tack on delimiter ourselves.
292 * Further note: UW-IMAP servers return nothing when asked for
293 * NAMESPACES without delimiters at the end. Argh! */
294 for (n--; n >= 0 && mbox[n] != list.delim; n--)
295 ; // do nothing
296
297 if (n > 0) /* "aaaa/bbbb/" -> "aaaa" */
298 {
299 /* forget the check, it is too delicate (see above). Have we ever
300 * had the parent not exist? */
301 ctmp = mbox[n];
302 mbox[n] = '\0';
303
304 if (showparents)
305 {
306 mutt_debug(LL_DEBUG3, "adding parent %s\n", mbox);
307 add_folder(list.delim, mbox, true, false, state, true);
308 }
309
310 /* if our target isn't a folder, we are in our superior */
311 if (!state->folder)
312 {
313 /* store folder with delimiter */
314 mbox[n++] = ctmp;
315 ctmp = mbox[n];
316 mbox[n] = '\0';
317 imap_qualify_path(buf, sizeof(buf), &cac, mbox);
318 state->folder = mutt_str_dup(buf);
319 }
320 mbox[n] = ctmp;
321 }
322 /* "/bbbb/" -> add "/", "aaaa/" -> add "" */
323 else
324 {
325 char relpath[2] = { 0 };
326 /* folder may be "/" */
327 snprintf(relpath, sizeof(relpath), "%c", (n < 0) ? '\0' : adata->delim);
328 if (showparents)
329 add_folder(adata->delim, relpath, true, false, state, true);
330 if (!state->folder)
331 {
332 imap_qualify_path(buf, sizeof(buf), &cac, relpath);
333 state->folder = mutt_str_dup(buf);
334 }
335 }
336 }
337
338 /* no namespace, no folder: set folder to host only */
339 if (!state->folder)
340 {
341 imap_qualify_path(buf, sizeof(buf), &cac, NULL);
342 state->folder = mutt_str_dup(buf);
343 }
344
345 mutt_debug(LL_DEBUG3, "Quoting mailbox scan: %s -> ", mbox);
346 snprintf(buf, sizeof(buf), "%s%%", mbox);
347 imap_munge_mbox_name(adata->unicode, munged_mbox, sizeof(munged_mbox), buf);
348 mutt_debug(LL_DEBUG3, "%s\n", munged_mbox);
349 len = snprintf(buf, sizeof(buf), "%s \"\" %s", list_cmd, munged_mbox);
351 snprintf(buf + len, sizeof(buf) - len, " RETURN (CHILDREN)");
352 if (browse_add_list_result(adata, buf, state, false))
353 goto fail;
354
355 if (ARRAY_EMPTY(&state->entry))
356 {
357 // L10N: (%s) is the name / path of the folder we were trying to browse
358 mutt_error(_("No such folder: %s"), path);
359 goto fail;
360 }
361
363
364 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed",
365 c_imap_check_subscribed, NULL);
366 return 0;
367
368fail:
369 cs_subset_str_native_set(NeoMutt->sub, "imap_check_subscribed",
370 c_imap_check_subscribed, NULL);
371 return -1;
372}
#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: logging.h:87
#define mutt_message(...)
Definition: logging.h:86
#define mutt_debug(LEVEL,...)
Definition: logging.h:84
struct ImapAccountData * imap_adata_get(struct Mailbox *m)
Get the Account data for this mailbox.
Definition: adata.c:89
static int browse_add_list_result(struct ImapAccountData *adata, const char *cmd, struct BrowserState *state, bool isparent)
Add entries to the folder browser.
Definition: browse.c:142
int imap_mxcmp(const char *mx1, const char *mx2)
Compare mailbox names, giving priority to INBOX.
Definition: util.c:553
char * imap_fix_path(char delim, const char *mailbox, char *path, size_t plen)
Fix up the imap path.
Definition: util.c:685
#define IMAP_CAP_LIST_EXTENDED
RFC5258: IMAP4 LIST Command Extensions.
Definition: private.h:140
bool imap_account_match(const struct ConnAccount *a1, const struct ConnAccount *a2)
Compare two Accounts.
Definition: util.c:1044
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:911
@ LL_DEBUG3
Log at debug level 3.
Definition: logging.h:42
@ 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:74
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:305
+ 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 382 of file browse.c.

383{
384 struct ImapAccountData *adata = NULL;
385 struct ImapMboxData *mdata = NULL;
386 struct Buffer *name = mutt_buffer_pool_get();
387 int rc = -1;
388
389 if (imap_adata_find(path, &adata, &mdata) < 0)
390 {
391 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
392 goto done;
393 }
394
395 /* append a delimiter if necessary */
396 const size_t n = mutt_buffer_strcpy(name, mdata->real_name);
397 if ((n != 0) && (name->data[n - 1] != adata->delim))
398 {
399 mutt_buffer_addch(name, adata->delim);
400 }
401
402 if (mutt_buffer_get_field(_("Create mailbox: "), name, MUTT_COMP_FILE, false,
403 NULL, NULL, NULL) != 0)
404 {
405 goto done;
406 }
407
408 if (mutt_buffer_is_empty(name))
409 {
410 mutt_error(_("Mailbox must have a name"));
411 goto done;
412 }
413
414 if (imap_create_mailbox(adata, mutt_buffer_string(name)) < 0)
415 goto done;
416
417 imap_mdata_free((void *) &mdata);
418 mutt_message(_("Mailbox created"));
419 mutt_sleep(0);
420 rc = 0;
421
422done:
423 imap_mdata_free((void *) &mdata);
425 return rc;
426}
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
size_t mutt_buffer_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:248
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_buffer_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:72
int imap_create_mailbox(struct ImapAccountData *adata, const char *mailbox)
Create a new mailbox.
Definition: imap.c:447
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
#define MUTT_COMP_FILE
File completion (in browser)
Definition: mutt.h:55
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1455
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
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 436 of file browse.c.

437{
438 struct ImapAccountData *adata = NULL;
439 struct ImapMboxData *mdata = NULL;
440 struct Buffer *buf = NULL;
441 struct Buffer *newname = NULL;
442 int rc = -1;
443
444 if (imap_adata_find(path, &adata, &mdata) < 0)
445 {
446 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
447 goto done;
448 }
449
450 if (mdata->real_name[0] == '\0')
451 {
452 mutt_error(_("Can't rename root folder"));
453 goto done;
454 }
455
456 buf = mutt_buffer_pool_get();
457 newname = mutt_buffer_pool_get();
458
459 mutt_buffer_printf(buf, _("Rename mailbox %s to: "), mdata->name);
460 mutt_buffer_strcpy(newname, mdata->name);
461
463 false, NULL, NULL, NULL) != 0)
464 {
465 goto done;
466 }
467
468 if (mutt_buffer_is_empty(newname))
469 {
470 mutt_error(_("Mailbox must have a name"));
471 goto done;
472 }
473
474 imap_fix_path(adata->delim, mutt_buffer_string(newname), buf->data, buf->dsize);
475
476 if (imap_rename_mailbox(adata, mdata->name, mutt_buffer_string(buf)) < 0)
477 {
478 mutt_error(_("Rename failed: %s"), imap_get_qualifier(adata->buf));
479 goto done;
480 }
481
482 mutt_message(_("Mailbox renamed"));
483 mutt_sleep(0);
484 rc = 0;
485
486done:
487 imap_mdata_free((void *) &mdata);
489 mutt_buffer_pool_release(&newname);
490
491 return rc;
492}
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
char * imap_get_qualifier(char *buf)
Get the qualifier from a tagged response.
Definition: util.c:772
int imap_rename_mailbox(struct ImapAccountData *adata, char *oldname, const char *newname)
Rename a mailbox.
Definition: imap.c:488
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: