/*
* Copyright (C) 1996-8 Michael R. Elkins <me@mutt.org>
* Copyright (C) 1996-9 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2007 Brendan Cully <brendan@kublai.com>
- *
+ * Copyright (C) 1999-2009 Brendan Cully <brendan@kublai.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
+ */
/* Support for IMAP4rev1, with the occasional nod to IMAP 4. */
}
imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox));
+ if (!*mailbox)
+ strfcpy (mailbox, "INBOX", sizeof (mailbox));
/* we may already be in the folder we're checking */
if (!ascii_strcmp(idata->mailbox, mx.mbox))
imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
snprintf (buf, sizeof (buf), "CREATE %s", mbox);
-
+
if (imap_exec (idata, buf, 0) != 0)
+ {
+ mutt_error (_("CREATE failed: %s"), imap_cmd_trailer (idata));
return -1;
+ }
return 0;
}
/* imap_logout_all: close all open connections. Quick and dirty until we can
* make sure we've got all the context we need. */
-void imap_logout_all (void)
+void imap_logout_all (void)
{
CONNECTION* conn;
CONNECTION* tmp;
if (conn->account.type == M_ACCT_TYPE_IMAP && conn->fd >= 0)
{
mutt_message (_("Closing connection to %s..."), conn->account.host);
- imap_logout ((IMAP_DATA*) conn->data);
+ imap_logout ((IMAP_DATA**) (void*) &conn->data);
mutt_clear_error ();
- mutt_socket_close (conn);
mutt_socket_free (conn);
}
int r = 0;
dprint (2, (debugfile, "imap_read_literal: reading %ld bytes\n", bytes));
-
+
for (pos = 0; pos < bytes; pos++)
{
if (mutt_socket_readchar (idata->conn, &c) != 1)
{
dprint (1, (debugfile, "imap_read_literal: error during read, %ld bytes read\n", pos));
idata->status = IMAP_FATAL;
-
+
return -1;
}
r = 0;
#endif
fputc (c, fp);
-
+
if (pbar && !(pos % 1024))
mutt_progress_update (pbar, pos, -1);
#ifdef DEBUG
break;
}
if (!conn)
- return NULL; /* this happens when the initial connection fails */
+ return NULL; /* this happens when the initial connection fails */
if (!idata)
{
}
else
mutt_account_unsetpass (&idata->conn->account);
-
+
FREE (&idata->capstr);
}
if (new && idata->state == IMAP_AUTHENTICATED)
{
/* capabilities may have changed */
- imap_cmd_queue (idata, "CAPABILITY");
+ imap_exec (idata, "CAPABILITY", IMAP_CMD_QUEUE);
/* get root delimiter, '/' as default */
idata->delim = '/';
- imap_cmd_queue (idata, "LIST \"\" \"\"");
+ imap_exec (idata, "LIST \"\" \"\"", IMAP_CMD_QUEUE);
if (option (OPTIMAPCHECKSUBSCRIBED))
- imap_cmd_queue (idata, "LSUB \"\" \"*\"");
+ imap_exec (idata, "LSUB \"\" \"*\"", IMAP_CMD_QUEUE);
/* we may need the root delimiter before we open a mailbox */
imap_exec (idata, NULL, IMAP_CMD_FAIL_OK);
}
mutt_bit_isset (idata->capabilities, STARTTLS)))
{
int rc;
-
+
if (option(OPTSSLFORCETLS))
rc = M_YES;
else if ((rc = query_quadoption (OPT_SSLSTARTTLS,
mutt_sleep (1);
goto err_close_conn;
}
-#endif
+#endif
}
else if (ascii_strncasecmp ("* PREAUTH", idata->buf, 9) == 0)
{
if (imap_check_capabilities (idata) != 0)
goto bail;
FREE (&idata->capstr);
- }
+ }
else
{
imap_error ("imap_open_connection()", buf);
void imap_close_connection(IMAP_DATA* idata)
{
- mutt_socket_close (idata->conn);
- idata->state = IMAP_DISCONNECTED;
+ if (idata->state != IMAP_DISCONNECTED)
+ {
+ mutt_socket_close (idata->conn);
+ idata->state = IMAP_DISCONNECTED;
+ }
idata->seqno = idata->nextcmd = idata->lastcmd = idata->status = 0;
- memset (idata->cmds, 0, sizeof (IMAP_COMMAND) * IMAP_PIPELINE_DEPTH);
+ memset (idata->cmds, 0, sizeof (IMAP_COMMAND) * idata->cmdslots);
}
/* imap_get_flags: Make a simple list out of a FLAGS response.
int count = 0;
IMAP_MBOX mx, pmx;
int rc;
-
+
if (imap_parse_path (ctx->path, &mx))
{
mutt_error (_("%s is an invalid IMAP path"), ctx->path);
/* Clean up path and replace the one in the ctx */
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
+ if (!*buf)
+ strfcpy (buf, "INBOX", sizeof (buf));
FREE(&(idata->mailbox));
idata->mailbox = safe_strdup (buf);
imap_qualify_path (buf, sizeof (buf), &mx, idata->mailbox);
mutt_message (_("Selecting %s..."), idata->mailbox);
imap_munge_mbox_name (buf, sizeof(buf), idata->mailbox);
-
+
/* pipeline ACL test */
if (mutt_bit_isset (idata->capabilities, ACL))
{
snprintf (bufout, sizeof (bufout), "MYRIGHTS %s", buf);
- imap_cmd_queue (idata, bufout);
+ imap_exec (idata, bufout, IMAP_CMD_QUEUE);
}
/* assume we have all rights if ACL is unavailable */
else
do
{
char *pc;
-
+
if ((rc = imap_cmd_step (idata)) != IMAP_CMD_CONTINUE)
break;
/* don't override PERMANENTFLAGS */
if (!idata->flags)
{
- dprint (2, (debugfile, "Getting mailbox FLAGS\n"));
+ dprint (3, (debugfile, "Getting mailbox FLAGS\n"));
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
goto fail;
}
/* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
else if (ascii_strncasecmp ("OK [PERMANENTFLAGS", pc, 18) == 0)
{
- dprint (2, (debugfile, "Getting mailbox PERMANENTFLAGS\n"));
+ dprint (3, (debugfile, "Getting mailbox PERMANENTFLAGS\n"));
/* safe to call on NULL */
mutt_free_list (&(idata->flags));
/* skip "OK [PERMANENT" so syntax is the same as FLAGS */
/* save UIDVALIDITY for the header cache */
else if (ascii_strncasecmp ("OK [UIDVALIDITY", pc, 14) == 0)
{
- dprint (2, (debugfile, "Getting mailbox UIDVALIDITY\n"));
+ dprint (3, (debugfile, "Getting mailbox UIDVALIDITY\n"));
pc += 3;
pc = imap_next_word (pc);
idata->uid_validity = strtol (pc, NULL, 10);
}
else if (ascii_strncasecmp ("OK [UIDNEXT", pc, 11) == 0)
{
- dprint (2, (debugfile, "Getting mailbox UIDNEXT\n"));
+ dprint (3, (debugfile, "Getting mailbox UIDNEXT\n"));
pc += 3;
pc = imap_next_word (pc);
idata->uidnext = strtol (pc, NULL, 10);
ctx->data = idata;
imap_fix_path (idata, mx.mbox, mailbox, sizeof (mailbox));
+ if (!*mailbox)
+ strfcpy (mailbox, "INBOX", sizeof (mailbox));
FREE (&mx.mbox);
/* really we should also check for W_OK */
}
/* imap_logout: Gracefully log out of server. */
-void imap_logout (IMAP_DATA* idata)
+void imap_logout (IMAP_DATA** idata)
{
/* we set status here to let imap_handle_untagged know we _expect_ to
* receive a bye response (so it doesn't freak out and close the conn) */
- idata->status = IMAP_BYE;
- imap_cmd_start (idata, "LOGOUT");
- while (imap_cmd_step (idata) == IMAP_CMD_CONTINUE)
+ (*idata)->status = IMAP_BYE;
+ imap_cmd_start (*idata, "LOGOUT");
+ while (imap_cmd_step (*idata) == IMAP_CMD_CONTINUE)
;
- FREE(& idata->buf);
- mutt_bcache_close (&idata->bcache);
- FREE(& idata);
+ mutt_socket_close ((*idata)->conn);
+ imap_free_idata (idata);
}
/* imap_set_flag: append str to flags if we currently have permission
{
if (!flag_list)
return 0;
-
+
flag_list = flag_list->next;
while (flag_list)
{
if (!ascii_strncasecmp (flag_list->data, flag, strlen (flag_list->data)))
return 1;
-
+
if (!ascii_strncmp (flag_list->data, "\\*", strlen (flag_list->data)))
return 1;
-
+
flag_list = flag_list->next;
}
-
+
return 0;
}
-/* imap_make_msg_set: make an IMAP4rev1 UID message set out of a set of
- * headers, given a flag enum to filter on.
- * Params: idata: IMAP_DATA containing context containing header set
- * buf: to write message set into
- * flag: enum of flag type on which to filter
- * changed: include only changed messages in message set
- * invert: invert sense of flag, eg M_READ matches unread messages
- * Returns: number of messages in message set (0 if no matches) */
-int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag, int changed,
- int invert)
+/* Note: headers must be in SORT_ORDER. See imap_exec_msgset for args.
+ * Pos is an opaque pointer a la strtok. It should be 0 at first call. */
+static int imap_make_msg_set (IMAP_DATA* idata, BUFFER* buf, int flag,
+ int changed, int invert, int* pos)
{
- HEADER** hdrs; /* sorted local copy */
+ HEADER** hdrs = idata->ctx->hdrs;
int count = 0; /* number of messages in message set */
int match = 0; /* whether current message matches flag condition */
unsigned int setstart = 0; /* start of current message range */
int n;
- short oldsort; /* we clobber reverse, must restore it */
int started = 0;
- if (Sort != SORT_ORDER)
- {
- hdrs = safe_calloc (idata->ctx->msgcount, sizeof (HEADER*));
- memcpy (hdrs, idata->ctx->hdrs, idata->ctx->msgcount * sizeof (HEADER*));
-
- oldsort = Sort;
- Sort = SORT_ORDER;
- qsort ((void*) hdrs, idata->ctx->msgcount, sizeof (HEADER*),
- mutt_get_sort_func (SORT_ORDER));
- Sort = oldsort;
- }
- else
- hdrs = idata->ctx->hdrs;
-
- for (n = 0; n < idata->ctx->msgcount; n++)
+ hdrs = idata->ctx->hdrs;
+
+ for (n = *pos;
+ n < idata->ctx->msgcount && buf->dptr - buf->data < IMAP_MAX_CMDLEN;
+ n++)
{
match = 0;
/* don't include pending expunged messages */
}
}
- if (Sort != SORT_ORDER)
- FREE (&hdrs);
+ *pos = n;
return count;
}
+/* Prepares commands for all messages matching conditions (must be flushed
+ * with imap_exec)
+ * Params:
+ * idata: IMAP_DATA containing context containing header set
+ * pre, post: commands are of the form "%s %s %s %s", tag,
+ * pre, message set, post
+ * flag: enum of flag type on which to filter
+ * changed: include only changed messages in message set
+ * invert: invert sense of flag, eg M_READ matches unread messages
+ * Returns: number of matched messages, or -1 on failure */
+int imap_exec_msgset (IMAP_DATA* idata, const char* pre, const char* post,
+ int flag, int changed, int invert)
+{
+ HEADER** hdrs = NULL;
+ short oldsort;
+ BUFFER* cmd;
+ int pos;
+ int rc;
+ int count = 0;
+
+ if (! (cmd = mutt_buffer_init (NULL)))
+ {
+ dprint (1, (debugfile, "imap_exec_msgset: unable to allocate buffer\n"));
+ return -1;
+ }
+
+ /* We make a copy of the headers just in case resorting doesn't give
+ exactly the original order (duplicate messages?), because other parts of
+ the ctx are tied to the header order. This may be overkill. */
+ oldsort = Sort;
+ if (Sort != SORT_ORDER)
+ {
+ hdrs = idata->ctx->hdrs;
+ idata->ctx->hdrs = safe_malloc (idata->ctx->msgcount * sizeof (HEADER*));
+ memcpy (idata->ctx->hdrs, hdrs, idata->ctx->msgcount * sizeof (HEADER*));
+
+ Sort = SORT_ORDER;
+ qsort (idata->ctx->hdrs, idata->ctx->msgcount, sizeof (HEADER*),
+ mutt_get_sort_func (SORT_ORDER));
+ }
+
+ pos = 0;
+
+ do
+ {
+ cmd->dptr = cmd->data;
+ mutt_buffer_printf (cmd, "%s ", pre);
+ rc = imap_make_msg_set (idata, cmd, flag, changed, invert, &pos);
+ if (rc > 0)
+ {
+ mutt_buffer_printf (cmd, " %s", post);
+ if (imap_exec (idata, cmd->data, IMAP_CMD_QUEUE))
+ {
+ rc = -1;
+ goto out;
+ }
+ count += rc;
+ }
+ }
+ while (rc > 0);
+
+ rc = count;
+
+out:
+ mutt_buffer_free (&cmd);
+ if (oldsort != Sort)
+ {
+ Sort = oldsort;
+ FREE (&idata->ctx->hdrs);
+ idata->ctx->hdrs = hdrs;
+ }
+
+ return rc;
+}
+
/* returns 0 if mutt's flags match cached server flags */
static int compare_flags (HEADER* h)
{
}
/* Update the IMAP server to reflect the flags a single message. */
-
int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
int *err_continue)
{
mutt_buffer_addstr (cmd, uid);
flags[0] = '\0';
-
+
imap_set_flag (idata, M_ACL_SEEN, hdr->read, "\\Seen ",
flags, sizeof (flags));
imap_set_flag (idata, M_ACL_WRITE, hdr->old,
return 0;
}
-static int sync_helper (IMAP_DATA* idata, BUFFER* buf, int right, int flag,
- const char* name)
+static int sync_helper (IMAP_DATA* idata, int right, int flag, const char* name)
{
- int rc = 0;
+ int count = 0;
+ int rc;
+
+ char buf[LONG_STRING];
if (!mutt_bit_isset (idata->ctx->rights, right))
return 0;
-
+
if (right == M_ACL_WRITE && !imap_has_flag (idata->flags, name))
return 0;
- buf->dptr = buf->data;
- mutt_buffer_addstr (buf, "UID STORE ");
- if (imap_make_msg_set (idata, buf, flag, 1, 0))
- {
- rc++;
- mutt_buffer_printf (buf, " +FLAGS.SILENT (%s)", name);
- imap_cmd_queue (idata, buf->data);
- }
- buf->dptr = buf->data;
- mutt_buffer_addstr (buf, "UID STORE ");
- if (imap_make_msg_set (idata, buf, flag, 1, 1))
- {
- rc++;
- mutt_buffer_printf (buf, " -FLAGS.SILENT (%s)", name);
- imap_cmd_queue (idata, buf->data);
- }
-
- return rc;
+ snprintf (buf, sizeof(buf), "+FLAGS.SILENT (%s)", name);
+ if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 0)) < 0)
+ return rc;
+ count += rc;
+
+ buf[0] = '-';
+ if ((rc = imap_exec_msgset (idata, "UID STORE", buf, flag, 1, 1)) < 0)
+ return rc;
+ count += rc;
+
+ return count;
}
/* update the IMAP server to reflect message changes done within mutt.
* Arguments
* ctx: the current context
- * expunge: 0 or 1 - do expunge?
+ * expunge: 0 or 1 - do expunge?
*/
int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
{
IMAP_DATA* idata;
CONTEXT* appendctx = NULL;
- BUFFER cmd;
HEADER* h;
HEADER** hdrs = NULL;
int oldsort;
- int deleted;
int n;
int rc;
-
+
idata = (IMAP_DATA*) ctx->data;
if (idata->state < IMAP_SELECTED)
return -1;
}
- /* This function is only called when the calling code expects the context
+ /* This function is only called when the calling code expects the context
* to be changed. */
imap_allow_reopen (ctx);
if ((rc = imap_check_mailbox (ctx, index_hint, 0)) != 0)
return rc;
- memset (&cmd, 0, sizeof (cmd));
-
/* if we are expunging anyway, we can do deleted messages very quickly... */
- if (expunge && mutt_bit_isset (idata->ctx->rights, M_ACL_DELETE))
+ if (expunge && mutt_bit_isset (ctx->rights, M_ACL_DELETE))
{
- mutt_buffer_addstr (&cmd, "UID STORE ");
- deleted = imap_make_msg_set (idata, &cmd, M_DELETED, 1, 0);
+ if ((rc = imap_exec_msgset (idata, "UID STORE", "+FLAGS.SILENT (\\Deleted)",
+ M_DELETED, 1, 0)) < 0)
+ {
+ mutt_error (_("Expunge failed"));
+ mutt_sleep (1);
+ goto out;
+ }
- /* if we have a message set, then let's delete */
- if (deleted)
+ if (rc > 0)
{
- mutt_message (_("Marking %d messages deleted..."), deleted);
- mutt_buffer_addstr (&cmd, " +FLAGS.SILENT (\\Deleted)");
/* mark these messages as unchanged so second pass ignores them. Done
* here so BOGUS UW-IMAP 4.7 SILENT FLAGS updates are ignored. */
for (n = 0; n < ctx->msgcount; n++)
- if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed)
- ctx->hdrs[n]->active = 0;
- if (imap_exec (idata, cmd.data, 0) != 0)
- {
- mutt_error (_("Expunge failed"));
- mutt_sleep (1);
- rc = -1;
- goto out;
- }
+ if (ctx->hdrs[n]->deleted && ctx->hdrs[n]->changed)
+ ctx->hdrs[n]->active = 0;
+ mutt_message (_("Marking %d messages deleted..."), rc);
}
}
imap_hcache_del (idata, HEADER_DATA(h)->uid);
#endif
}
-
+
if (h->active && h->changed)
{
+#if USE_HCACHE
+ imap_hcache_put (idata, h);
+#endif
/* if the message has been rethreaded or attachments have been deleted
* we delete the message and reupload it.
* This works better if we're expunging, of course. */
if (!appendctx)
appendctx = mx_open_mailbox (ctx->path, M_APPEND | M_QUIET, NULL);
if (!appendctx)
- {
dprint (1, (debugfile, "imap_sync_mailbox: Error opening mailbox in append mode\n"));
- }
else
_mutt_save_message (h, appendctx, 1, 0, 0);
}
/* sync +/- flags for the five flags mutt cares about */
rc = 0;
- /* presort here to avoid doing 10 resorts in imap_make_msg_set */
+ /* presort here to avoid doing 10 resorts in imap_exec_msgset */
oldsort = Sort;
if (Sort != SORT_ORDER)
{
ctx->hdrs = safe_malloc (ctx->msgcount * sizeof (HEADER*));
memcpy (ctx->hdrs, hdrs, ctx->msgcount * sizeof (HEADER*));
- oldsort = Sort;
Sort = SORT_ORDER;
qsort (ctx->hdrs, ctx->msgcount, sizeof (HEADER*),
mutt_get_sort_func (SORT_ORDER));
}
- rc += sync_helper (idata, &cmd, M_ACL_DELETE, M_DELETED, "\\Deleted");
- rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_FLAG, "\\Flagged");
- rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_OLD, "Old");
- rc += sync_helper (idata, &cmd, M_ACL_SEEN, M_READ, "\\Seen");
- rc += sync_helper (idata, &cmd, M_ACL_WRITE, M_REPLIED, "\\Answered");
+ rc += sync_helper (idata, M_ACL_DELETE, M_DELETED, "\\Deleted");
+ rc += sync_helper (idata, M_ACL_WRITE, M_FLAG, "\\Flagged");
+ rc += sync_helper (idata, M_ACL_WRITE, M_OLD, "Old");
+ rc += sync_helper (idata, M_ACL_SEEN, M_READ, "\\Seen");
+ rc += sync_helper (idata, M_ACL_WRITE, M_REPLIED, "\\Answered");
if (oldsort != Sort)
{
ctx->hdrs = hdrs;
}
- if (rc)
+ if (rc && (imap_exec (idata, NULL, 0) != IMAP_CMD_OK))
{
- if ((rc = imap_exec (idata, NULL, 0)) != IMAP_CMD_OK)
+ if (ctx->closing)
{
- if (ctx->closing)
+ if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES)
{
- if (mutt_yesorno (_("Error saving flags. Close anyway?"), 0) == M_YES)
- {
- rc = 0;
- idata->state = IMAP_AUTHENTICATED;
- goto out;
- }
+ rc = 0;
+ idata->state = IMAP_AUTHENTICATED;
+ goto out;
}
- else
- mutt_error _("Error saving flags");
- goto out;
}
+ else
+ mutt_error _("Error saving flags");
+ goto out;
}
+
for (n = 0; n < ctx->msgcount; n++)
ctx->hdrs[n]->changed = 0;
ctx->changed = 0;
/* We must send an EXPUNGE command if we're not closing. */
if (expunge && !(ctx->closing) &&
- mutt_bit_isset(idata->ctx->rights, M_ACL_DELETE))
+ mutt_bit_isset(ctx->rights, M_ACL_DELETE))
{
mutt_message _("Expunging messages from server...");
/* Set expunge bit so we don't get spurious reopened messages */
if (expunge && ctx->closing)
{
- imap_cmd_queue (idata, "CLOSE");
+ imap_exec (idata, "CLOSE", IMAP_CMD_QUEUE);
idata->state = IMAP_AUTHENTICATED;
}
rc = 0;
out:
- if (cmd.data)
- FREE (&cmd.data);
if (appendctx)
{
mx_fastclose_mailbox (appendctx);
/* mx_close_mailbox won't sync if there are no deleted messages
* and the mailbox is unchanged, so we may have to close here */
if (!ctx->deleted)
- imap_cmd_queue (idata, "CLOSE");
- if (idata->state == IMAP_IDLE)
- {
- mutt_buffer_addstr (idata->cmdbuf, "DONE\r\n");
- idata->state = IMAP_SELECTED;
- }
+ imap_exec (idata, "CLOSE", IMAP_CMD_QUEUE);
idata->state = IMAP_AUTHENTICATED;
}
if (!force && option (OPTIMAPIDLE) && mutt_bit_isset (idata->capabilities, IDLE)
&& (idata->state != IMAP_IDLE || time(NULL) >= idata->lastread + ImapKeepalive))
{
- imap_cmd_start (idata, "IDLE");
- idata->state = IMAP_IDLE;
- do
- result = imap_cmd_step (idata);
- while (result == IMAP_CMD_CONTINUE);
- /* it's possible that we were notified and fetched mail before
- * getting to the +, in which case we've automatically unidled. */
- if (result != IMAP_CMD_RESPOND && result != IMAP_CMD_OK)
- {
- dprint (1, (debugfile, "Error starting IDLE\n"));
- idata->state = IMAP_SELECTED;
+ if (imap_cmd_idle (idata) < 0)
return -1;
- }
}
if (idata->state == IMAP_IDLE)
{
}
}
- if ((force ||
+ if ((force ||
(idata->state != IMAP_IDLE && time(NULL) >= idata->lastread + Timeout))
&& imap_exec (idata, "NOOP", 0) != 0)
return -1;
FREE (&mx.mbox);
return -1;
}
-
+
imap_fix_path (*hidata, mx.mbox, buf, blen);
+ if (!*buf)
+ strfcpy (buf, "INBOX", blen);
FREE (&mx.mbox);
return 0;
if (mx_is_imap (mailbox->path))
mailbox->magic = M_IMAP;
}
-
+
if (mailbox->magic != M_IMAP)
continue;
continue;
/* Don't issue STATUS on the selected mailbox, it will be NOOPed or
- * IDLEd elsewhere */
- if (!imap_mxcmp (name, idata->mailbox))
+ * IDLEd elsewhere.
+ * idata->mailbox may be NULL for connections other than the current
+ * mailbox's, and shouldn't expand to INBOX in that case. #3216. */
+ if (idata->mailbox && !imap_mxcmp (name, idata->mailbox))
continue;
if (!mutt_bit_isset (idata->capabilities, IMAP4REV1) &&
snprintf (command, sizeof (command),
"STATUS %s (UIDNEXT UIDVALIDITY UNSEEN RECENT)", munged);
- if (imap_cmd_queue (idata, command) < 0)
+ if (imap_exec (idata, command, IMAP_CMD_QUEUE) < 0)
{
- /* pipeline must be full, drain it */
- dprint (2, (debugfile, "IMAP command pipeline full, draining\n"));
-
- if (imap_exec (idata, NULL, IMAP_CMD_FAIL_OK) == -1)
- dprint (1, (debugfile, "Error polling mailboxes\n"));
-
- if (imap_cmd_queue (idata, command) < 0) {
- /* real trouble */
- dprint (1, (debugfile, "Error queueing command\n"));
- return 0;
- }
+ dprint (1, (debugfile, "Error queueing command\n"));
+ return 0;
}
}
if (queue)
{
- imap_cmd_queue (idata, buf);
+ imap_exec (idata, buf, IMAP_CMD_QUEUE);
queued = 1;
return 0;
}
queued = 0;
if ((status = imap_mboxcache_get (idata, mbox, 0)))
return status->messages;
-
+
return 0;
}
unsigned int *uidvalidity = NULL;
unsigned int *uidnext = NULL;
#endif
-
+
for (cur = idata->mboxcache; cur; cur = cur->next)
{
status = (IMAP_STATUS*)cur->data;
if (pat->child && do_search (pat->child, 1))
rc++;
}
-
+
if (!allpats)
break;
}
-
+
return rc;
}
if (pat->op == M_OR && clauses > 1)
mutt_buffer_addstr (buf, "OR ");
clauses--;
-
+
if (imap_compile_search (clause, buf) < 0)
return -1;
if (clauses)
mutt_buffer_addch (buf, ' ');
-
- clause = clause->next;
+
}
+ clause = clause->next;
}
mutt_buffer_addch (buf, ')');
imap_quote_string (term, sizeof (term), pat->p.str);
mutt_buffer_addstr (buf, term);
mutt_buffer_addch (buf, ' ');
-
+
/* and field */
*delim = ':';
delim++;
}
if (!(idata = imap_conn_find (&(mx.account), 0)))
goto fail;
-
+
conn = idata->conn;
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
+ if (!*buf)
+ strfcpy (buf, "INBOX", sizeof (buf));
if (option (OPTIMAPCHECKSUBSCRIBED))
{
dprint (1, (debugfile, "Error adding subscribed mailbox: %s\n", errstr));
FREE (&token.data);
}
-
+
if (subscribe)
mutt_message (_("Subscribing to %s..."), buf);
else
longest_common_prefix (char *dest, const char* src, int start, size_t dlen)
{
int pos = start;
-
+
while (pos < dlen && dest[pos] && dest[pos] == src[pos])
pos++;
dest[pos] = '\0';
CONNECTION* conn;
int rc = -1;
int matchlen;
-
+
matchlen = mutt_strlen (dest);
for (mailbox = Incoming; mailbox; mailbox = mailbox->next)
{
longest_common_prefix (dest, mailbox->path, matchlen, len);
}
}
-
+
for (conn = mutt_socket_head (); conn; conn = conn->next)
{
ciss_url_t url;
{
/* reformat output */
imap_qualify_path (dest, dlen, &mx, completion);
- mutt_pretty_mailbox (dest);
+ mutt_pretty_mailbox (dest, dlen);
FREE (&mx.mbox);
return 0;
}
-
+
return -1;
}