2 * Copyright (C) 1996-8 Michael R. Elkins <me@mutt.org>
3 * Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
4 * Copyright (C) 1999-2009 Brendan Cully <brendan@kublai.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 /* Support for IMAP4rev1, with the occasional nod to IMAP 4. */
34 #include "imap_private.h"
36 # include "mutt_ssl.h"
47 #include <sys/types.h>
50 /* imap forward declarations */
51 static char* imap_get_flags (LIST** hflags, char* s);
52 static int imap_check_capabilities (IMAP_DATA* idata);
53 static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,
54 const char* str, char* flags, size_t flsize);
56 /* imap_access: Check permissions on an IMAP mailbox.
57 * TODO: ACL checks. Right now we assume if it exists we can
59 int imap_access (const char* path, int flags)
63 char buf[LONG_STRING];
64 char mailbox[LONG_STRING];
65 char mbox[LONG_STRING];
68 if (imap_parse_path (path, &mx))
71 if (!(idata = imap_conn_find (&mx.account,
72 option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0)))
78 imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox));
80 strfcpy (mailbox, "INBOX", sizeof (mailbox));
82 /* we may already be in the folder we're checking */
83 if (!ascii_strcmp(idata->mailbox, mx.mbox))
90 if (imap_mboxcache_get (idata, mailbox, 0))
92 dprint (3, (debugfile, "imap_access: found %s in cache\n", mailbox));
96 imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
98 if (mutt_bit_isset (idata->capabilities, IMAP4REV1))
99 snprintf (buf, sizeof (buf), "STATUS %s (UIDVALIDITY)", mbox);
100 else if (mutt_bit_isset (idata->capabilities, STATUS))
101 snprintf (buf, sizeof (buf), "STATUS %s (UID-VALIDITY)", mbox);
104 dprint (2, (debugfile, "imap_access: STATUS not supported?\n"));
108 if ((rc = imap_exec (idata, buf, IMAP_CMD_FAIL_OK)) < 0)
110 dprint (1, (debugfile, "imap_access: Can't check STATUS of %s\n", mbox));
117 int imap_create_mailbox (IMAP_DATA* idata, char* mailbox)
119 char buf[LONG_STRING], mbox[LONG_STRING];
121 imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
122 snprintf (buf, sizeof (buf), "CREATE %s", mbox);
124 if (imap_exec (idata, buf, 0) != 0)
126 mutt_error (_("CREATE failed: %s"), imap_cmd_trailer (idata));
133 int imap_rename_mailbox (IMAP_DATA* idata, IMAP_MBOX* mx, const char* newname)
135 char oldmbox[LONG_STRING];
136 char newmbox[LONG_STRING];
137 char buf[LONG_STRING];
139 imap_munge_mbox_name (oldmbox, sizeof (oldmbox), mx->mbox);
140 imap_munge_mbox_name (newmbox, sizeof (newmbox), newname);
142 snprintf (buf, sizeof (buf), "RENAME %s %s", oldmbox, newmbox);
144 if (imap_exec (idata, buf, 0) != 0)
150 int imap_delete_mailbox (CONTEXT* ctx, IMAP_MBOX mx)
152 char buf[LONG_STRING], mbox[LONG_STRING];
155 if (!ctx || !ctx->data) {
156 if (!(idata = imap_conn_find (&mx.account,
157 option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0)))
166 imap_munge_mbox_name (mbox, sizeof (mbox), mx.mbox);
167 snprintf (buf, sizeof (buf), "DELETE %s", mbox);
169 if (imap_exec ((IMAP_DATA*) idata, buf, 0) != 0)
175 /* imap_logout_all: close all open connections. Quick and dirty until we can
176 * make sure we've got all the context we need. */
177 void imap_logout_all (void)
182 conn = mutt_socket_head ();
188 if (conn->account.type == M_ACCT_TYPE_IMAP && conn->fd >= 0)
190 mutt_message (_("Closing connection to %s..."), conn->account.host);
191 imap_logout ((IMAP_DATA**) (void*) &conn->data);
193 mutt_socket_free (conn);
200 /* imap_read_literal: read bytes bytes from server into file. Not explicitly
201 * buffered, relies on FILE buffering. NOTE: strips \r from \r\n.
202 * Apparently even literals use \r\n-terminated strings ?! */
203 int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes, progress_t* pbar)
210 dprint (2, (debugfile, "imap_read_literal: reading %ld bytes\n", bytes));
212 for (pos = 0; pos < bytes; pos++)
214 if (mutt_socket_readchar (idata->conn, &c) != 1)
216 dprint (1, (debugfile, "imap_read_literal: error during read, %ld bytes read\n", pos));
217 idata->status = IMAP_FATAL;
223 if (r == 1 && c != '\n')
236 if (pbar && !(pos % 1024))
237 mutt_progress_update (pbar, pos, -1);
239 if (debuglevel >= IMAP_LOG_LTRL)
240 fputc (c, debugfile);
247 /* imap_expunge_mailbox: Purge IMAP portion of expunged messages from the
248 * context. Must not be done while something has a handle on any headers
249 * (eg inside pager or editor). That is, check IMAP_REOPEN_ALLOW. */
250 void imap_expunge_mailbox (IMAP_DATA* idata)
256 idata->hcache = imap_hcache_open (idata, NULL);
259 for (i = 0; i < idata->ctx->msgcount; i++)
261 h = idata->ctx->hdrs[i];
265 dprint (2, (debugfile, "Expunging message UID %d.\n", HEADER_DATA (h)->uid));
268 idata->ctx->size -= h->content->length;
270 imap_cache_del (idata, h);
272 imap_hcache_del (idata, HEADER_DATA(h)->uid);
275 /* free cached body from disk, if necessary */
276 cacheno = HEADER_DATA(h)->uid % IMAP_CACHE_LEN;
277 if (idata->cache[cacheno].uid == HEADER_DATA(h)->uid &&
278 idata->cache[cacheno].path)
280 unlink (idata->cache[cacheno].path);
281 FREE (&idata->cache[cacheno].path);
284 imap_free_header_data (&h->data);
289 imap_hcache_close (idata);
292 /* We may be called on to expunge at any time. We can't rely on the caller
293 * to always know to rethread */
294 mx_update_tables (idata->ctx, 0);
295 mutt_sort_headers (idata->ctx, 1);
298 /* imap_check_capabilities: make sure we can log in to this server. */
299 static int imap_check_capabilities (IMAP_DATA* idata)
301 if (imap_exec (idata, "CAPABILITY", 0) != 0)
303 imap_error ("imap_check_capabilities", idata->buf);
307 if (!(mutt_bit_isset(idata->capabilities,IMAP4)
308 ||mutt_bit_isset(idata->capabilities,IMAP4REV1)))
310 mutt_error _("This IMAP server is ancient. Mutt does not work with it.");
311 mutt_sleep (2); /* pause a moment to let the user see the error */
319 /* imap_conn_find: Find an open IMAP connection matching account, or open
320 * a new one if none can be found. */
321 IMAP_DATA* imap_conn_find (const ACCOUNT* account, int flags)
323 CONNECTION* conn = NULL;
324 ACCOUNT* creds = NULL;
325 IMAP_DATA* idata = NULL;
328 while ((conn = mutt_conn_find (conn, account)))
331 creds = &conn->account;
333 memcpy (&conn->account, creds, sizeof (ACCOUNT));
335 idata = (IMAP_DATA*)conn->data;
336 if (flags & M_IMAP_CONN_NONEW)
340 /* This should only happen if we've come to the end of the list */
341 mutt_socket_free (conn);
344 else if (idata->state < IMAP_AUTHENTICATED)
347 if (flags & M_IMAP_CONN_NOSELECT && idata && idata->state >= IMAP_SELECTED)
349 if (idata && idata->status == IMAP_FATAL)
354 return NULL; /* this happens when the initial connection fails */
358 /* The current connection is a new connection */
359 if (! (idata = imap_new_idata ()))
361 mutt_socket_free (conn);
370 if (idata->state == IMAP_DISCONNECTED)
371 imap_open_connection (idata);
372 if (idata->state == IMAP_CONNECTED)
374 if (!imap_authenticate (idata))
376 idata->state = IMAP_AUTHENTICATED;
378 if (idata->conn->ssf)
379 dprint (2, (debugfile, "Communication encrypted at %d bits\n",
383 mutt_account_unsetpass (&idata->conn->account);
385 FREE (&idata->capstr);
387 if (new && idata->state == IMAP_AUTHENTICATED)
389 /* capabilities may have changed */
390 imap_exec (idata, "CAPABILITY", IMAP_CMD_QUEUE);
391 /* get root delimiter, '/' as default */
393 imap_exec (idata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
394 if (option (OPTIMAPCHECKSUBSCRIBED))
395 imap_exec (idata, "LSUB \"\" \"*\"", IMAP_CMD_QUEUE);
396 /* we may need the root delimiter before we open a mailbox */
397 imap_exec (idata, NULL, IMAP_CMD_FAIL_OK);
403 int imap_open_connection (IMAP_DATA* idata)
405 char buf[LONG_STRING];
407 if (mutt_socket_open (idata->conn) < 0)
410 idata->state = IMAP_CONNECTED;
412 if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
414 imap_close_connection (idata);
418 if (ascii_strncasecmp ("* OK", idata->buf, 4) == 0)
420 if (ascii_strncasecmp ("* OK [CAPABILITY", idata->buf, 16)
421 && imap_check_capabilities (idata))
424 /* Attempt STARTTLS if available and desired. */
425 if (!idata->conn->ssf && (option(OPTSSLFORCETLS) ||
426 mutt_bit_isset (idata->capabilities, STARTTLS)))
430 if (option(OPTSSLFORCETLS))
432 else if ((rc = query_quadoption (OPT_SSLSTARTTLS,
433 _("Secure connection with TLS?"))) == -1)
436 if ((rc = imap_exec (idata, "STARTTLS", IMAP_CMD_FAIL_OK)) == -1)
440 if (mutt_ssl_starttls (idata->conn))
442 mutt_error (_("Could not negotiate TLS connection"));
448 /* RFC 2595 demands we recheck CAPABILITY after TLS completes. */
449 if (imap_exec (idata, "CAPABILITY", 0))
456 if (option(OPTSSLFORCETLS) && ! idata->conn->ssf)
458 mutt_error _("Encrypted connection unavailable");
464 else if (ascii_strncasecmp ("* PREAUTH", idata->buf, 9) == 0)
466 idata->state = IMAP_AUTHENTICATED;
467 if (imap_check_capabilities (idata) != 0)
469 FREE (&idata->capstr);
473 imap_error ("imap_open_connection()", buf);
481 imap_close_connection (idata);
484 FREE (&idata->capstr);
488 void imap_close_connection(IMAP_DATA* idata)
490 if (idata->state != IMAP_DISCONNECTED)
492 mutt_socket_close (idata->conn);
493 idata->state = IMAP_DISCONNECTED;
495 idata->seqno = idata->nextcmd = idata->lastcmd = idata->status = 0;
496 memset (idata->cmds, 0, sizeof (IMAP_COMMAND) * idata->cmdslots);
499 /* imap_get_flags: Make a simple list out of a FLAGS response.
500 * return stream following FLAGS response */
501 static char* imap_get_flags (LIST** hflags, char* s)
507 /* sanity-check string */
508 if (ascii_strncasecmp ("FLAGS", s, 5) != 0)
510 dprint (1, (debugfile, "imap_get_flags: not a FLAGS response: %s\n",
518 dprint (1, (debugfile, "imap_get_flags: bogus FLAGS response: %s\n",
523 /* create list, update caller's flags handle */
524 flags = mutt_new_list();
527 while (*s && *s != ')')
532 while (*s && (*s != ')') && !ISSPACE (*s))
537 mutt_add_list (flags, flag_word);
541 /* note bad flags response */
544 dprint (1, (debugfile,
545 "imap_get_flags: Unterminated FLAGS response: %s\n", s));
546 mutt_free_list (hflags);
556 int imap_open_mailbox (CONTEXT* ctx)
561 char buf[LONG_STRING];
562 char bufout[LONG_STRING];
567 if (imap_parse_path (ctx->path, &mx))
569 mutt_error (_("%s is an invalid IMAP path"), ctx->path);
573 /* we require a connection which isn't currently in IMAP_SELECTED state */
574 if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NOSELECT)))
576 if (idata->state < IMAP_AUTHENTICATED)
581 /* once again the context is new */
583 ctx->mx_close = imap_close_mailbox;
585 /* Clean up path and replace the one in the ctx */
586 imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
588 strfcpy (buf, "INBOX", sizeof (buf));
589 FREE(&(idata->mailbox));
590 idata->mailbox = safe_strdup (buf);
591 imap_qualify_path (buf, sizeof (buf), &mx, idata->mailbox);
594 ctx->path = safe_strdup (buf);
598 /* clear mailbox status */
600 memset (idata->ctx->rights, 0, sizeof (idata->ctx->rights));
601 idata->newMailCount = 0;
603 mutt_message (_("Selecting %s..."), idata->mailbox);
604 imap_munge_mbox_name (buf, sizeof(buf), idata->mailbox);
606 /* pipeline ACL test */
607 if (mutt_bit_isset (idata->capabilities, ACL))
609 snprintf (bufout, sizeof (bufout), "MYRIGHTS %s", buf);
610 imap_exec (idata, bufout, IMAP_CMD_QUEUE);
612 /* assume we have all rights if ACL is unavailable */
615 mutt_bit_set (idata->ctx->rights, M_ACL_LOOKUP);
616 mutt_bit_set (idata->ctx->rights, M_ACL_READ);
617 mutt_bit_set (idata->ctx->rights, M_ACL_SEEN);
618 mutt_bit_set (idata->ctx->rights, M_ACL_WRITE);
619 mutt_bit_set (idata->ctx->rights, M_ACL_INSERT);
620 mutt_bit_set (idata->ctx->rights, M_ACL_POST);
621 mutt_bit_set (idata->ctx->rights, M_ACL_CREATE);
622 mutt_bit_set (idata->ctx->rights, M_ACL_DELETE);
624 /* pipeline the postponed count if possible */
626 if (mx_is_imap (Postponed) && !imap_parse_path (Postponed, &pmx)
627 && mutt_account_match (&pmx.account, &mx.account))
628 imap_status (Postponed, 1);
631 snprintf (bufout, sizeof (bufout), "%s %s",
632 ctx->readonly ? "EXAMINE" : "SELECT", buf);
634 idata->state = IMAP_SELECTED;
636 imap_cmd_start (idata, bufout);
638 status = imap_mboxcache_get (idata, idata->mailbox, 1);
644 if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
649 /* Obtain list of available flags here, may be overridden by a
650 * PERMANENTFLAGS tag in the OK response */
651 if (ascii_strncasecmp ("FLAGS", pc, 5) == 0)
653 /* don't override PERMANENTFLAGS */
656 dprint (3, (debugfile, "Getting mailbox FLAGS\n"));
657 if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
661 /* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
662 else if (ascii_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0)
664 dprint (3, (debugfile, "Getting mailbox PERMANENTFLAGS\n"));
665 /* safe to call on NULL */
666 mutt_free_list (&(idata->flags));
667 /* skip "OK [PERMANENT" so syntax is the same as FLAGS */
669 if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
672 /* save UIDVALIDITY for the header cache */
673 else if (ascii_strncasecmp ("OK [UIDVALIDITY", pc, 14) == 0)
675 dprint (3, (debugfile, "Getting mailbox UIDVALIDITY\n"));
677 pc = imap_next_word (pc);
678 idata->uid_validity = strtol (pc, NULL, 10);
679 status->uidvalidity = idata->uid_validity;
681 else if (ascii_strncasecmp ("OK [UIDNEXT", pc, 11) == 0)
683 dprint (3, (debugfile, "Getting mailbox UIDNEXT\n"));
685 pc = imap_next_word (pc);
686 idata->uidnext = strtol (pc, NULL, 10);
687 status->uidnext = idata->uidnext;
691 pc = imap_next_word (pc);
692 if (!ascii_strncasecmp ("EXISTS", pc, 6))
694 count = idata->newMailCount;
695 idata->newMailCount = 0;
699 while (rc == IMAP_CMD_CONTINUE);
701 if (rc == IMAP_CMD_NO)
704 s = imap_next_word (idata->buf); /* skip seq */
705 s = imap_next_word (s); /* Skip response */
706 mutt_error ("%s", s);
711 if (rc != IMAP_CMD_OK)
714 /* check for READ-ONLY notification */
715 if (!ascii_strncasecmp (imap_get_qualifier (idata->buf), "[READ-ONLY]", 11) \
716 && !mutt_bit_isset (idata->capabilities, ACL))
718 dprint (2, (debugfile, "Mailbox is read-only.\n"));
723 /* dump the mailbox flags we've found */
727 dprint (3, (debugfile, "No folder flags found\n"));
730 LIST* t = idata->flags;
732 dprint (3, (debugfile, "Mailbox flags: "));
737 dprint (3, (debugfile, "[%s] ", t->data));
740 dprint (3, (debugfile, "\n"));
745 if (!(mutt_bit_isset(idata->ctx->rights, M_ACL_DELETE) ||
746 mutt_bit_isset(idata->ctx->rights, M_ACL_SEEN) ||
747 mutt_bit_isset(idata->ctx->rights, M_ACL_WRITE) ||
748 mutt_bit_isset(idata->ctx->rights, M_ACL_INSERT)))
752 ctx->hdrs = safe_calloc (count, sizeof (HEADER *));
753 ctx->v2r = safe_calloc (count, sizeof (int));
756 if (count && (imap_read_headers (idata, 0, count-1) < 0))
758 mutt_error _("Error opening mailbox");
763 dprint (2, (debugfile, "imap_open_mailbox: msgcount is %d\n", ctx->msgcount));
768 if (idata->state == IMAP_SELECTED)
769 idata->state = IMAP_AUTHENTICATED;
775 int imap_open_mailbox_append (CONTEXT *ctx)
779 char buf[LONG_STRING];
780 char mailbox[LONG_STRING];
784 if (imap_parse_path (ctx->path, &mx))
787 /* in APPEND mode, we appear to hijack an existing IMAP connection -
788 * ctx is brand new and mostly empty */
790 if (!(idata = imap_conn_find (&(mx.account), 0)))
801 imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox));
803 strfcpy (mailbox, "INBOX", sizeof (mailbox));
806 /* really we should also check for W_OK */
807 if ((rc = imap_access (ctx->path, F_OK)) == 0)
813 snprintf (buf, sizeof (buf), _("Create %s?"), mailbox);
814 if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
817 if (imap_create_mailbox (idata, mailbox) < 0)
823 /* imap_logout: Gracefully log out of server. */
824 void imap_logout (IMAP_DATA** idata)
826 /* we set status here to let imap_handle_untagged know we _expect_ to
827 * receive a bye response (so it doesn't freak out and close the conn) */
828 (*idata)->status = IMAP_BYE;
829 imap_cmd_start (*idata, "LOGOUT");
830 while (imap_cmd_step (*idata) == IMAP_CMD_CONTINUE)
833 mutt_socket_close ((*idata)->conn);
834 imap_free_idata (idata);
837 /* imap_set_flag: append str to flags if we currently have permission
838 * according to aclbit */
839 static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,
840 const char *str, char *flags, size_t flsize)
842 if (mutt_bit_isset (idata->ctx->rights, aclbit))
843 if (flag && imap_has_flag (idata->flags, str))
844 safe_strcat (flags, flsize, str);
847 /* imap_has_flag: do a caseless comparison of the flag against a flag list,
848 * return 1 if found or flag list has '\*', 0 otherwise */
849 int imap_has_flag (LIST* flag_list, const char* flag)
854 flag_list = flag_list->next;
857 if (!ascii_strncasecmp (flag_list->data, flag, strlen (flag_list->data)))
860 if (!ascii_strncmp (flag_list->data, "\\*", strlen (flag_list->data)))
863 flag_list = flag_list->next;
869 /* Note: headers must be in SORT_ORDER. See imap_exec_msgset for args.
870 * Pos is an opaque pointer a la strtok. It should be 0 at first call. */
871 static int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag,
872 int changed, int invert, int* pos)
874 HEADER** hdrs = idata->ctx->hdrs;
875 int count = 0; /* number of messages in message set */
876 int match = 0; /* whether current message matches flag condition */
877 unsigned int setstart = 0; /* start of current message range */
881 hdrs = idata->ctx->hdrs;
884 n < idata->ctx->msgcount && buf->dptr - buf->data < IMAP_MAX_CMDLEN;
888 /* don't include pending expunged messages */
893 if (hdrs[n]->deleted != HEADER_DATA(hdrs[n])->deleted)
894 match = invert ^ hdrs[n]->deleted;
897 if (hdrs[n]->flagged != HEADER_DATA(hdrs[n])->flagged)
898 match = invert ^ hdrs[n]->flagged;
901 if (hdrs[n]->old != HEADER_DATA(hdrs[n])->old)
902 match = invert ^ hdrs[n]->old;
905 if (hdrs[n]->read != HEADER_DATA(hdrs[n])->read)
906 match = invert ^ hdrs[n]->read;
909 if (hdrs[n]->replied != HEADER_DATA(hdrs[n])->replied)
910 match = invert ^ hdrs[n]->replied;
919 if (match && (!changed || hdrs[n]->changed))
924 setstart = HEADER_DATA (hdrs[n])->uid;
927 mutt_buffer_printf (buf, "%u", HEADER_DATA (hdrs[n])->uid);
931 mutt_buffer_printf (buf, ",%u", HEADER_DATA (hdrs[n])->uid);
933 /* tie up if the last message also matches */
934 else if (n == idata->ctx->msgcount-1)
935 mutt_buffer_printf (buf, ":%u", HEADER_DATA (hdrs[n])->uid);
937 /* End current set if message doesn't match or we've reached the end
938 * of the mailbox via inactive messages following the last match. */
939 else if (setstart && (hdrs[n]->active || n == idata->ctx->msgcount-1))
941 if (HEADER_DATA (hdrs[n-1])->uid > setstart)
942 mutt_buffer_printf (buf, ":%u", HEADER_DATA (hdrs[n-1])->uid);
952 /* Prepares commands for all messages matching conditions (must be flushed
955 * idata: IMAP_DATA containing context containing header set
956 * pre, post: commands are of the form "%s %s %s %s", tag,
957 * pre, message set, post
958 * flag: enum of flag type on which to filter
959 * changed: include only changed messages in message set
960 * invert: invert sense of flag, eg M_READ matches unread messages
961 * Returns: number of matched messages, or -1 on failure */
962 int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post,
963 int flag, int changed, int invert)
965 HEADER** hdrs = NULL;
972 if (! (cmd = mutt_buffer_init (NULL)))
974 dprint (1, (debugfile, "imap_exec_msgset: unable to allocate buffer\n"));
978 /* We make a copy of the headers just in case resorting doesn't give
979 exactly the original order (duplicate messages?), because other parts of
980 the ctx are tied to the header order. This may be overkill. */
982 if (Sort != SORT_ORDER)
984 hdrs = idata->ctx->hdrs;
985 idata->ctx->hdrs = safe_malloc (idata->ctx->msgcount * sizeof (HEADER*));
986 memcpy (idata->ctx->hdrs, hdrs, idata->ctx->msgcount * sizeof (HEADER*));
989 qsort (idata->ctx->hdrs, idata->ctx->msgcount, sizeof (HEADER*),
990 mutt_get_sort_func (SORT_ORDER));
997 cmd->dptr = cmd->data;
998 mutt_buffer_printf (cmd, "%s ", pre);
999 rc = imap_make_msg_set (idata, cmd, flag, changed, invert, &pos);
1002 mutt_buffer_printf (cmd, " %s", post);
1003 if (imap_exec (idata, cmd->data, IMAP_CMD_QUEUE))
1016 mutt_buffer_free (&cmd);
1017 if (oldsort != Sort)
1020 FREE (&idata->ctx->hdrs);
1021 idata->ctx->hdrs = hdrs;
1027 /* returns 0 if mutt's flags match cached server flags */
1028 static int compare_flags (HEADER* h)
1030 IMAP_HEADER_DATA* hd = (IMAP_HEADER_DATA*)h->data;
1032 if (h->read != hd->read)
1034 if (h->old != hd->old)
1036 if (h->flagged != hd->flagged)
1038 if (h->replied != hd->replied)
1040 if (h->deleted != hd->deleted)
1046 /* Update the IMAP server to reflect the flags a single message. */
1047 int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
1050 char flags[LONG_STRING];
1055 if (!compare_flags (hdr))
1057 idata->ctx->changed--;
1061 snprintf (uid, sizeof (uid), "%u", HEADER_DATA(hdr)->uid);
1062 cmd->dptr = cmd->data;
1063 mutt_buffer_addstr (cmd, "UID STORE ");
1064 mutt_buffer_addstr (cmd, uid);
1068 imap_set_flag (idata, M_ACL_SEEN, hdr->read, "\\Seen ",
1069 flags, sizeof (flags));
1070 imap_set_flag (idata, M_ACL_WRITE, hdr->old,
1071 "Old ", flags, sizeof (flags));
1072 imap_set_flag (idata, M_ACL_WRITE, hdr->flagged,
1073 "\\Flagged ", flags, sizeof (flags));
1074 imap_set_flag (idata, M_ACL_WRITE, hdr->replied,
1075 "\\Answered ", flags, sizeof (flags));
1076 imap_set_flag (idata, M_ACL_DELETE, hdr->deleted,
1077 "\\Deleted ", flags, sizeof (flags));
1079 /* now make sure we don't lose custom tags */
1080 if (mutt_bit_isset (idata->ctx->rights, M_ACL_WRITE))
1081 imap_add_keywords (flags, hdr, idata->flags, sizeof (flags));
1083 mutt_remove_trailing_ws (flags);
1085 /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
1086 * explicitly revoke all system flags (if we have permission) */
1089 imap_set_flag (idata, M_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags));
1090 imap_set_flag (idata, M_ACL_WRITE, 1, "Old ", flags, sizeof (flags));
1091 imap_set_flag (idata, M_ACL_WRITE, 1, "\\Flagged ", flags, sizeof (flags));
1092 imap_set_flag (idata, M_ACL_WRITE, 1, "\\Answered ", flags, sizeof (flags));
1093 imap_set_flag (idata, M_ACL_DELETE, 1, "\\Deleted ", flags, sizeof (flags));
1095 mutt_remove_trailing_ws (flags);
1097 mutt_buffer_addstr (cmd, " -FLAGS.SILENT (");
1099 mutt_buffer_addstr (cmd, " FLAGS.SILENT (");
1101 mutt_buffer_addstr (cmd, flags);
1102 mutt_buffer_addstr (cmd, ")");
1104 /* dumb hack for bad UW-IMAP 4.7 servers spurious FLAGS updates */
1107 /* after all this it's still possible to have no flags, if you
1108 * have no ACL rights */
1109 if (*flags && (imap_exec (idata, cmd->data, 0) != 0) &&
1110 err_continue && (*err_continue != M_YES))
1112 *err_continue = imap_continue ("imap_sync_message: STORE failed",
1114 if (*err_continue != M_YES)
1119 idata->ctx->changed--;
1124 static int sync_helper (IMAP_DATA* idata, int right, int flag, const char* name)
1129 char buf[LONG_STRING];
1131 if (!mutt_bit_isset (idata->ctx->rights, right))
1134 if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name))
1137 snprintf (buf, sizeof(buf), "+FLAGS.SILENT (%s)", name);
1138 if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 0)) < 0)
1143 if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 1)) < 0)
1150 /* update the IMAP server to reflect message changes done within mutt.
1152 * ctx: the current context
1153 * expunge: 0 or 1 - do expunge?
1155 int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
1158 CONTEXT* appendctx = NULL;
1160 HEADER** hdrs = NULL;
1165 idata = (IMAP_DATA*) ctx->data;
1167 if (idata->state < IMAP_SELECTED)
1169 dprint (2, (debugfile, "imap_sync_mailbox: no mailbox selected\n"));
1173 /* This function is only called when the calling code expects the context
1175 imap_allow_reopen (ctx);
1177 if ((rc = imap_check_mailbox (ctx, index_hint, 0)) != 0)
1180 /* if we are expunging anyway, we can do deleted messages very quickly... */
1181 if (expunge && mutt_bit_isset (ctx->rights, M_ACL_DELETE))
1183 if ((rc = imap_exec_msgset (idata, "UID STORE", "+FLAGS.SILENT (\\Deleted)",
1184 M_DELETED, 1, 0)) < 0)
1186 mutt_error (_("Expunge failed"));
1193 /* mark these messages as unchanged so second pass ignores them. Done
1194 * here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
1195 for (n = 0; n < ctx->msgcount; n++)
1196 if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed)
1197 ctx->hdrs[n]->active = 0;
1198 mutt_message (_("Marking %d messages deleted..."), rc);
1203 idata->hcache = imap_hcache_open (idata, NULL);
1206 /* save messages with real (non-flag) changes */
1207 for (n = 0; n < ctx->msgcount; n++)
1213 imap_cache_del (idata, h);
1215 imap_hcache_del (idata, HEADER_DATA(h)->uid);
1219 if (h->active && h->changed)
1222 imap_hcache_put (idata, h);
1224 /* if the message has been rethreaded or attachments have been deleted
1225 * we delete the message and reupload it.
1226 * This works better if we're expunging, of course. */
1227 if ((h->env && (h->env->refs_changed || h->env->irt_changed)) ||
1230 mutt_message (_("Saving changed messages... [%d/%d]"), n+1,
1233 appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL);
1235 dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n"));
1237 _mutt_save_message (h, appendctx, 1, 0, 0);
1243 imap_hcache_close (idata);
1246 /* sync +/- flags for the five flags mutt cares about */
1249 /* presort here to avoid doing 10 resorts in imap_exec_msgset */
1251 if (Sort != SORT_ORDER)
1254 ctx->hdrs = safe_malloc (ctx->msgcount * sizeof (HEADER*));
1255 memcpy (ctx->hdrs, hdrs, ctx->msgcount * sizeof (HEADER*));
1258 qsort (ctx->hdrs, ctx->msgcount, sizeof (HEADER*),
1259 mutt_get_sort_func (SORT_ORDER));
1262 rc += sync_helper (idata, M_ACL_DELETE, M_DELETED, "\\Deleted");
1263 rc += sync_helper (idata, M_ACL_WRITE, M_FLAG, "\\Flagged");
1264 rc += sync_helper (idata, M_ACL_WRITE, M_OLD, "Old");
1265 rc += sync_helper (idata, M_ACL_SEEN, M_READ, "\\Seen");
1266 rc += sync_helper (idata, M_ACL_WRITE, M_REPLIED, "\\Answered");
1268 if (oldsort != Sort)
1275 if (rc && (imap_exec (idata, NULL, 0) != IMAP_CMD_OK))
1279 if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES)
1282 idata->state = IMAP_AUTHENTICATED;
1287 mutt_error _("Error saving flags");
1291 for (n = 0; n < ctx->msgcount; n++)
1292 ctx->hdrs[n]->changed = 0;
1295 /* We must send an EXPUNGE command if we're not closing. */
1296 if (expunge && !(ctx->closing) &&
1297 mutt_bit_isset(ctx->rights, M_ACL_DELETE))
1299 mutt_message _("Expunging messages from server...");
1300 /* Set expunge bit so we don't get spurious reopened messages */
1301 idata->reopen |= IMAP_EXPUNGE_EXPECTED;
1302 if (imap_exec (idata, "EXPUNGE", 0) != 0)
1304 imap_error (_("imap_sync_mailbox: EXPUNGE failed"), idata->buf);
1310 if (expunge && ctx->closing)
1312 imap_exec (idata, "CLOSE", IMAP_CMD_QUEUE);
1313 idata->state = IMAP_AUTHENTICATED;
1316 if (option (OPTMESSAGECACHECLEAN))
1317 imap_cache_clean (idata);
1324 mx_fastclose_mailbox (appendctx);
1330 /* imap_close_mailbox: clean up IMAP data in CONTEXT */
1331 int imap_close_mailbox (CONTEXT* ctx)
1336 idata = (IMAP_DATA*) ctx->data;
1337 /* Check to see if the mailbox is actually open */
1341 if (ctx == idata->ctx)
1343 if (idata->status != IMAP_FATAL && idata->state >= IMAP_SELECTED)
1345 /* mx_close_mailbox won't sync if there are no deleted messages
1346 * and the mailbox is unchanged, so we may have to close here */
1348 imap_exec (idata, "CLOSE", IMAP_CMD_QUEUE);
1349 idata->state = IMAP_AUTHENTICATED;
1352 idata->reopen &= IMAP_REOPEN_ALLOW;
1353 FREE (&(idata->mailbox));
1354 mutt_free_list (&idata->flags);
1358 /* free IMAP part of headers */
1359 for (i = 0; i < ctx->msgcount; i++)
1360 /* mailbox may not have fully loaded */
1361 if (ctx->hdrs[i] && ctx->hdrs[i]->data)
1362 imap_free_header_data (&(ctx->hdrs[i]->data));
1364 for (i = 0; i < IMAP_CACHE_LEN; i++)
1366 if (idata->cache[i].path)
1368 unlink (idata->cache[i].path);
1369 FREE (&idata->cache[i].path);
1373 mutt_bcache_close (&idata->bcache);
1378 /* use the NOOP or IDLE command to poll for new mail
1381 * M_REOPENED mailbox has been externally modified
1382 * M_NEW_MAIL new mail has arrived!
1386 int imap_check_mailbox (CONTEXT *ctx, int *index_hint, int force)
1388 /* overload keyboard timeout to avoid many mailbox checks in a row.
1389 * Most users don't like having to wait exactly when they press a key. */
1393 idata = (IMAP_DATA*) ctx->data;
1395 /* try IDLE first, unless force is set */
1396 if (!force && option (OPTIMAPIDLE) && mutt_bit_isset (idata->capabilities, IDLE)
1397 && (idata->state != IMAP_IDLE || time(NULL) >= idata->lastread + ImapKeepalive))
1399 if (imap_cmd_idle (idata) < 0)
1402 if (idata->state == IMAP_IDLE)
1404 while ((result = mutt_socket_poll (idata->conn)) > 0)
1406 if (imap_cmd_step (idata) != IMAP_CMD_CONTINUE)
1408 dprint (1, (debugfile, "Error reading IDLE response\n"));
1414 dprint (1, (debugfile, "Poll failed, disabling IDLE\n"));
1415 mutt_bit_unset (idata->capabilities, IDLE);
1420 (idata->state != IMAP_IDLE && time(NULL) >= idata->lastread + Timeout))
1421 && imap_exec (idata, "NOOP", 0) != 0)
1424 /* We call this even when we haven't run NOOP in case we have pending
1425 * changes to process, since we can reopen here. */
1426 imap_cmd_finish (idata);
1428 if (idata->check_status & IMAP_EXPUNGE_PENDING)
1429 result = M_REOPENED;
1430 else if (idata->check_status & IMAP_NEWMAIL_PENDING)
1431 result = M_NEW_MAIL;
1432 else if (idata->check_status & IMAP_FLAGS_PENDING)
1435 idata->check_status = 0;
1440 /* split path into (idata,mailbox name) */
1441 static int imap_get_mailbox (const char* path, IMAP_DATA** hidata, char* buf, size_t blen)
1445 if (imap_parse_path (path, &mx))
1447 dprint (1, (debugfile, "imap_get_mailbox: Error parsing %s\n", path));
1450 if (!(*hidata = imap_conn_find (&(mx.account), option (OPTIMAPPASSIVE) ? M_IMAP_CONN_NONEW : 0))
1451 || (*hidata)->state < IMAP_AUTHENTICATED)
1457 imap_fix_path (*hidata, mx.mbox, buf, blen);
1459 strfcpy (buf, "INBOX", blen);
1465 /* check for new mail in any subscribed mailboxes. Given a list of mailboxes
1466 * rather than called once for each so that it can batch the commands and
1467 * save on round trips. Returns number of mailboxes with new mail. */
1468 int imap_buffy_check (int force)
1471 IMAP_DATA* lastdata = NULL;
1473 char name[LONG_STRING];
1474 char command[LONG_STRING];
1475 char munged[LONG_STRING];
1478 for (mailbox = Incoming; mailbox; mailbox = mailbox->next)
1480 /* Init newly-added mailboxes */
1481 if (! mailbox->magic)
1483 if (mx_is_imap (mailbox->path))
1484 mailbox->magic = M_IMAP;
1487 if (mailbox->magic != M_IMAP)
1492 if (imap_get_mailbox (mailbox->path, &idata, name, sizeof (name)) < 0)
1495 /* Don't issue STATUS on the selected mailbox, it will be NOOPed or
1497 * idata->mailbox may be NULL for connections other than the current
1498 * mailbox's, and shouldn't expand to INBOX in that case. #3216. */
1499 if (idata->mailbox && !imap_mxcmp (name, idata->mailbox))
1502 if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) &&
1503 !mutt_bit_isset (idata->capabilities, STATUS))
1505 dprint (2, (debugfile, "Server doesn't support STATUS\n"));
1509 if (lastdata && idata != lastdata)
1511 /* Send commands to previous server. Sorting the buffy list
1512 * may prevent some infelicitous interleavings */
1513 if (imap_exec (lastdata, NULL, IMAP_CMD_FAIL_OK) == -1)
1514 dprint (1, (debugfile, "Error polling mailboxes\n"));
1522 imap_munge_mbox_name (munged, sizeof (munged), name);
1523 snprintf (command, sizeof (command),
1524 "STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
1526 if (imap_exec (idata, command, IMAP_CMD_QUEUE) < 0)
1528 dprint (1, (debugfile, "Error queueing command\n"));
1533 if (lastdata && (imap_exec (lastdata, NULL, IMAP_CMD_FAIL_OK) == -1))
1535 dprint (1, (debugfile, "Error polling mailboxes\n"));
1539 /* collect results */
1540 for (mailbox = Incoming; mailbox; mailbox = mailbox->next)
1542 if (mailbox->magic == M_IMAP && mailbox->new)
1549 /* imap_status: returns count of messages in mailbox, or -1 on error.
1550 * if queue != 0, queue the command and expect it to have been run
1551 * on the next call (for pipelining the postponed count) */
1552 int imap_status (char* path, int queue)
1554 static int queued = 0;
1557 char buf[LONG_STRING];
1558 char mbox[LONG_STRING];
1559 IMAP_STATUS* status;
1561 if (imap_get_mailbox (path, &idata, buf, sizeof (buf)) < 0)
1564 if (!imap_mxcmp (buf, idata->mailbox))
1565 /* We are in the folder we're polling - just return the mailbox count */
1566 return idata->ctx->msgcount;
1567 else if (mutt_bit_isset(idata->capabilities,IMAP4REV1) ||
1568 mutt_bit_isset(idata->capabilities,STATUS))
1570 imap_munge_mbox_name (mbox, sizeof(mbox), buf);
1571 snprintf (buf, sizeof (buf), "STATUS %s (%s)", mbox, "MESSAGES");
1572 imap_unmunge_mbox_name (mbox);
1575 /* Server does not support STATUS, and this is not the current mailbox.
1576 * There is no lightweight way to check recent arrivals */
1581 imap_exec (idata, buf, IMAP_CMD_QUEUE);
1586 imap_exec (idata, buf, 0);
1589 if ((status = imap_mboxcache_get (idata, mbox, 0)))
1590 return status->messages;
1595 /* return cached mailbox stats or NULL if create is 0 */
1596 IMAP_STATUS* imap_mboxcache_get (IMAP_DATA* idata, const char* mbox, int create)
1599 IMAP_STATUS* status;
1602 header_cache_t *hc = NULL;
1603 unsigned int *uidvalidity = NULL;
1604 unsigned int *uidnext = NULL;
1607 for (cur = idata->mboxcache; cur; cur = cur->next)
1609 status = (IMAP_STATUS*)cur->data;
1611 if (!imap_mxcmp (mbox, status->name))
1619 memset (&scache, 0, sizeof (scache));
1620 scache.name = (char*)mbox;
1621 idata->mboxcache = mutt_add_list_n (idata->mboxcache, &scache,
1623 status = imap_mboxcache_get (idata, mbox, 0);
1624 status->name = safe_strdup (mbox);
1628 hc = imap_hcache_open (idata, mbox);
1631 uidvalidity = mutt_hcache_fetch_raw (hc, "/UIDVALIDITY", imap_hcache_keylen);
1632 uidnext = mutt_hcache_fetch_raw (hc, "/UIDNEXT", imap_hcache_keylen);
1633 mutt_hcache_close (hc);
1638 FREE (&uidvalidity);
1640 return imap_mboxcache_get (idata, mbox, 1);
1642 status->uidvalidity = *uidvalidity;
1643 status->uidnext = uidnext ? *uidnext: 0;
1644 dprint (3, (debugfile, "mboxcache: hcache uidvalidity %d, uidnext %d\n",
1645 status->uidvalidity, status->uidnext));
1647 FREE (&uidvalidity);
1655 void imap_mboxcache_free (IMAP_DATA* idata)
1658 IMAP_STATUS* status;
1660 for (cur = idata->mboxcache; cur; cur = cur->next)
1662 status = (IMAP_STATUS*)cur->data;
1664 FREE (&status->name);
1667 mutt_free_list (&idata->mboxcache);
1670 /* returns number of patterns in the search that should be done server-side
1671 * (eg are full-text) */
1672 static int do_search (const pattern_t* search, int allpats)
1675 const pattern_t* pat;
1677 for (pat = search; pat; pat = pat->next)
1684 if (pat->stringmatch)
1688 if (pat->child && do_search (pat->child, 1))
1699 /* convert mutt pattern_t to IMAP SEARCH command containing only elements
1700 * that require full-text search (mutt already has what it needs for most
1701 * match types, and does a better job (eg server doesn't support regexps). */
1702 static int imap_compile_search (const pattern_t* pat, BUFFER* buf)
1704 if (! do_search (pat, 0))
1708 mutt_buffer_addstr (buf, "NOT ");
1714 if ((clauses = do_search (pat->child, 1)) > 0)
1716 const pattern_t* clause = pat->child;
1718 mutt_buffer_addch (buf, '(');
1722 if (do_search (clause, 0))
1724 if (pat->op == M_OR && clauses > 1)
1725 mutt_buffer_addstr (buf, "OR ");
1728 if (imap_compile_search (clause, buf) < 0)
1732 mutt_buffer_addch (buf, ' ');
1735 clause = clause->next;
1738 mutt_buffer_addch (buf, ')');
1749 mutt_buffer_addstr (buf, "HEADER ");
1751 /* extract header name */
1752 if (! (delim = strchr (pat->p.str, ':')))
1754 mutt_error (_("Header search without header name: %s"), pat->p.str);
1758 imap_quote_string (term, sizeof (term), pat->p.str);
1759 mutt_buffer_addstr (buf, term);
1760 mutt_buffer_addch (buf, ' ');
1766 imap_quote_string (term, sizeof (term), delim);
1767 mutt_buffer_addstr (buf, term);
1770 mutt_buffer_addstr (buf, "BODY ");
1771 imap_quote_string (term, sizeof (term), pat->p.str);
1772 mutt_buffer_addstr (buf, term);
1775 mutt_buffer_addstr (buf, "TEXT ");
1776 imap_quote_string (term, sizeof (term), pat->p.str);
1777 mutt_buffer_addstr (buf, term);
1785 int imap_search (CONTEXT* ctx, const pattern_t* pat)
1788 IMAP_DATA* idata = (IMAP_DATA*)ctx->data;
1791 for (i = 0; i < ctx->msgcount; i++)
1792 ctx->hdrs[i]->matched = 0;
1794 if (!do_search (pat, 1))
1797 memset (&buf, 0, sizeof (buf));
1798 mutt_buffer_addstr (&buf, "UID SEARCH ");
1799 if (imap_compile_search (pat, &buf) < 0)
1804 if (imap_exec (idata, buf.data, 0) < 0)
1814 int imap_subscribe (char *path, int subscribe)
1818 char buf[LONG_STRING];
1819 char mbox[LONG_STRING];
1820 char errstr[STRING];
1824 if (!mx_is_imap (path) || imap_parse_path (path, &mx) || !mx.mbox)
1826 mutt_error (_("Bad mailbox name"));
1829 if (!(idata = imap_conn_find (&(mx.account), 0)))
1834 imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
1836 strfcpy (buf, "INBOX", sizeof (buf));
1838 if (option (OPTIMAPCHECKSUBSCRIBED))
1840 memset (&token, 0, sizeof (token));
1842 err.dsize = sizeof (errstr);
1843 snprintf (mbox, sizeof (mbox), "%smailboxes \"%s\"",
1844 subscribe ? "" : "un", path);
1845 if (mutt_parse_rc_line (mbox, &token, &err))
1846 dprint (1, (debugfile, "Error adding subscribed mailbox: %s\n", errstr));
1851 mutt_message (_("Subscribing to %s..."), buf);
1853 mutt_message (_("Unsubscribing from %s..."), buf);
1854 imap_munge_mbox_name (mbox, sizeof(mbox), buf);
1856 snprintf (buf, sizeof (buf), "%sSUBSCRIBE %s", subscribe ? "" : "UN", mbox);
1858 if (imap_exec (idata, buf, 0) < 0)
1861 imap_unmunge_mbox_name(mx.mbox);
1863 mutt_message (_("Subscribed to %s"), mx.mbox);
1865 mutt_message (_("Unsubscribed from %s"), mx.mbox);
1874 /* trim dest to the length of the longest prefix it shares with src,
1875 * returning the length of the trimmed string */
1877 longest_common_prefix (char *dest, const char* src, int start, size_t dlen)
1881 while (pos < dlen && dest[pos] && dest[pos] == src[pos])
1888 /* look for IMAP URLs to complete from defined mailboxes. Could be extended
1889 * to complete over open connections and account/folder hooks too. */
1891 imap_complete_hosts (char *dest, size_t len)
1898 matchlen = mutt_strlen (dest);
1899 for (mailbox = Incoming; mailbox; mailbox = mailbox->next)
1901 if (!mutt_strncmp (dest, mailbox->path, matchlen))
1905 strfcpy (dest, mailbox->path, len);
1909 longest_common_prefix (dest, mailbox->path, matchlen, len);
1913 for (conn = mutt_socket_head (); conn; conn = conn->next)
1916 char urlstr[LONG_STRING];
1918 if (conn->account.type != M_ACCT_TYPE_IMAP)
1921 mutt_account_tourl (&conn->account, &url);
1922 /* FIXME: how to handle multiple users on the same host? */
1925 url_ciss_tostring (&url, urlstr, sizeof (urlstr), 0);
1926 if (!mutt_strncmp (dest, urlstr, matchlen))
1930 strfcpy (dest, urlstr, len);
1934 longest_common_prefix (dest, urlstr, matchlen, len);
1941 /* imap_complete: given a partial IMAP folder path, return a string which
1942 * adds as much to the path as is unique */
1943 int imap_complete(char* dest, size_t dlen, char* path) {
1946 char list[LONG_STRING];
1947 char buf[LONG_STRING];
1949 char completion[LONG_STRING];
1950 int clen, matchlen = 0;
1951 int completions = 0;
1955 if (imap_parse_path (path, &mx))
1957 strfcpy (dest, path, dlen);
1958 return imap_complete_hosts (dest, dlen);
1961 /* don't open a new socket just for completion. Instead complete over
1962 * known mailboxes/hooks/etc */
1963 if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NONEW)))
1966 strfcpy (dest, path, dlen);
1967 return imap_complete_hosts (dest, dlen);
1971 /* reformat path for IMAP list, and append wildcard */
1972 /* don't use INBOX in place of "" */
1973 if (mx.mbox && mx.mbox[0])
1974 imap_fix_path (idata, mx.mbox, list, sizeof(list));
1978 /* fire off command */
1979 snprintf (buf, sizeof(buf), "%s \"\" \"%s%%\"",
1980 option (OPTIMAPLSUB) ? "LSUB" : "LIST", list);
1982 imap_cmd_start (idata, buf);
1984 /* and see what the results are */
1985 strfcpy (completion, NONULL(mx.mbox), sizeof(completion));
1986 idata->cmdtype = IMAP_CT_LIST;
1987 idata->cmddata = &listresp;
1990 listresp.name = NULL;
1991 rc = imap_cmd_step (idata);
1993 if (rc == IMAP_CMD_CONTINUE && listresp.name)
1995 /* if the folder isn't selectable, append delimiter to force browse
1996 * to enter it on second tab. */
1997 if (listresp.noselect)
1999 clen = strlen(listresp.name);
2000 listresp.name[clen++] = listresp.delim;
2001 listresp.name[clen] = '\0';
2003 /* copy in first word */
2006 strfcpy (completion, listresp.name, sizeof(completion));
2007 matchlen = strlen (completion);
2012 matchlen = longest_common_prefix (completion, listresp.name, 0, matchlen);
2016 while (rc == IMAP_CMD_CONTINUE);
2017 idata->cmddata = NULL;
2021 /* reformat output */
2022 imap_qualify_path (dest, dlen, &mx, completion);
2023 mutt_pretty_mailbox (dest, dlen);