NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
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 "gui/lib.h"
#include "mutt.h"
#include "lib.h"
#include "browser/lib.h"
#include "editor/lib.h"
#include "history/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.
 
static int browse_add_list_result (struct ImapAccountData *adata, const char *cmd, struct BrowserState *bstate, bool isparent)
 Add entries to the folder browser.
 
int imap_browse (const char *path, struct BrowserState *state)
 IMAP hook into the folder browser.
 
int imap_mailbox_create (const char *path)
 Create a new IMAP mailbox.
 
int imap_mailbox_rename (const char *path)
 Rename a mailbox.
 

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 64 of file browse.c.

66{
67 char tmp[PATH_MAX] = { 0 };
68 char relpath[PATH_MAX] = { 0 };
69 struct ConnAccount cac = { { 0 } };
70 char mailbox[1024] = { 0 };
71 struct FolderFile ff = { 0 };
72
73 if (imap_parse_path(state->folder, &cac, mailbox, sizeof(mailbox)))
74 return;
75
76 if (isparent)
77 {
78 /* render superiors as unix-standard ".." */
79 mutt_str_copy(relpath, "../", sizeof(relpath));
80 }
81 else if (mutt_str_startswith(folder, mailbox))
82 {
83 /* strip current folder from target, to render a relative path */
84 mutt_str_copy(relpath, folder + mutt_str_len(mailbox), sizeof(relpath));
85 }
86 else
87 {
88 mutt_str_copy(relpath, folder, sizeof(relpath));
89 }
90
91 /* apply filemask filter. This should really be done at menu setup rather
92 * than at scan, since it's so expensive to scan. But that's big changes
93 * to browser.c */
94 const struct Regex *c_mask = cs_subset_regex(NeoMutt->sub, "mask");
95 if (!mutt_regex_match(c_mask, relpath))
96 {
97 return;
98 }
99
100 imap_qualify_path(tmp, sizeof(tmp), &cac, folder);
101 ff.name = mutt_str_dup(tmp);
102
103 /* mark desc with delim in browser if it can have subfolders */
104 if (!isparent && !noinferiors && (strlen(relpath) < sizeof(relpath) - 1))
105 {
106 relpath[strlen(relpath) + 1] = '\0';
107 relpath[strlen(relpath)] = delim;
108 }
109
110 ff.desc = mutt_str_dup(relpath);
111 ff.imap = true;
112
113 /* delimiter at the root is useless. */
114 if (folder[0] == '\0')
115 delim = '\0';
116 ff.delim = delim;
117 ff.selectable = !noselect;
118 ff.inferiors = !noinferiors;
119
120 struct MailboxList ml = STAILQ_HEAD_INITIALIZER(ml);
122 struct MailboxNode *np = NULL;
123 STAILQ_FOREACH(np, &ml, entries)
124 {
125 if (mutt_str_equal(tmp, mailbox_path(np->mailbox)))
126 break;
127 }
128
129 if (np)
130 {
131 ff.has_mailbox = true;
132 ff.has_new_mail = np->mailbox->has_new;
133 ff.msg_count = np->mailbox->msg_count;
134 ff.msg_unread = np->mailbox->msg_unread;
135 }
137
138 ARRAY_ADD(&state->entry, ff);
139}
#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:218
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:471
void imap_qualify_path(char *buf, size_t buflen, struct ConnAccount *conn_account, char *path)
Make an absolute IMAP folder target.
Definition: util.c:813
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:636
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:162
size_t neomutt_mailboxlist_get_all(struct MailboxList *head, struct NeoMutt *n, enum MailboxType type)
Get a List of all Mailboxes.
Definition: neomutt.c:185
#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:122
struct BrowserEntryArray entry
Array of files / dirs / mailboxes.
Definition: lib.h:119
Login details for a remote server.
Definition: connaccount.h:53
Browser entry representing a folder/dir.
Definition: lib.h:78
bool selectable
Folder can be selected.
Definition: lib.h:97
char delim
Path delimiter.
Definition: lib.h:94
bool imap
This is an IMAP folder.
Definition: lib.h:96
bool has_mailbox
This is a mailbox.
Definition: lib.h:100
char * name
Name of file/dir/mailbox.
Definition: lib.h:86
bool has_new_mail
true if mailbox has "new mail"
Definition: lib.h:89
char * desc
Description of mailbox.
Definition: lib.h:87
int msg_count
total number of messages
Definition: lib.h:90
bool inferiors
Folder has children.
Definition: lib.h:98
int msg_unread
number of unread messages
Definition: lib.h:91
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:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
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 150 of file browse.c.

152{
153 struct ImapList list = { 0 };
154 int rc;
155 struct Url *url = url_parse(bstate->folder);
156 if (!url)
157 return -1;
158
159 imap_cmd_start(adata, cmd);
160 adata->cmdresult = &list;
161 do
162 {
163 list.name = NULL;
164 rc = imap_cmd_step(adata);
165
166 if ((rc == IMAP_RES_CONTINUE) && list.name)
167 {
168 /* Let a parent folder never be selectable for navigation */
169 if (isparent)
170 list.noselect = true;
171 /* prune current folder from output */
172 if (isparent || !mutt_str_startswith(url->path, list.name))
173 add_folder(list.delim, list.name, list.noselect, list.noinferiors, bstate, isparent);
174 }
175 } while (rc == IMAP_RES_CONTINUE);
176 adata->cmdresult = NULL;
177
178 url_free(&url);
179
180 return (rc == IMAP_RES_OK) ? 0 : -1;
181}
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:64
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
Definition: command.c:1115
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
Definition: command.c:1129
#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 192 of file browse.c.

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

393{
394 struct ImapAccountData *adata = NULL;
395 struct ImapMboxData *mdata = NULL;
396 struct Buffer *name = buf_pool_get();
397 int rc = -1;
398
399 if (imap_adata_find(path, &adata, &mdata) < 0)
400 {
401 mutt_debug(LL_DEBUG1, "Couldn't find open connection to %s\n", path);
402 goto done;
403 }
404
405 /* append a delimiter if necessary */
406 const size_t n = buf_strcpy(name, mdata->real_name);
407 if ((n != 0) && (name->data[n - 1] != adata->delim))
408 {
409 buf_addch(name, adata->delim);
410 }
411
412 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
413 if (mw_get_field(_("Create mailbox: "), name, MUTT_COMP_NO_FLAGS, HC_FILE,
414 &CompleteMailboxOps, &cdata) != 0)
415 {
416 goto done;
417 }
418
419 if (buf_is_empty(name))
420 {
421 mutt_error(_("Mailbox must have a name"));
422 goto done;
423 }
424
425 if (imap_create_mailbox(adata, buf_string(name)) < 0)
426 goto done;
427
428 imap_mdata_free((void *) &mdata);
429 mutt_message(_("Mailbox created"));
430 mutt_sleep(0);
431 rc = 0;
432
433done:
434 imap_mdata_free((void *) &mdata);
435 buf_pool_release(&name);
436 return rc;
437}
const struct CompleteOps CompleteMailboxOps
Auto-Completion of Files / Mailboxes.
Definition: complete.c:160
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:407
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition: window.c:275
@ HC_FILE
Files.
Definition: lib.h:52
void imap_mdata_free(void **ptr)
Free the private Mailbox data - Implements Mailbox::mdata_free()
Definition: mdata.c:39
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:429
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1428
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
Input for the file completion function.
Definition: curs_lib.h:49
IMAP-specific Mailbox data -.
Definition: mdata.h:40
char * real_name
Original Mailbox name, e.g.: INBOX can be just \0.
Definition: mdata.h:43
void * mdata
Driver specific data.
Definition: mailbox.h:133
+ 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 447 of file browse.c.

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