summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OPS2
-rw-r--r--browser.c57
-rw-r--r--browser.h3
-rw-r--r--buffy.c64
-rw-r--r--doc/manual.sgml.head16
-rw-r--r--functions.h2
-rw-r--r--globals.h1
-rw-r--r--imap/browse.c78
-rw-r--r--imap/command.c2
-rw-r--r--imap/imap.c128
-rw-r--r--imap/imap.h2
-rw-r--r--imap/imap_private.h3
-rw-r--r--imap/message.c62
-rw-r--r--imap/util.c13
-rw-r--r--init.h6
15 files changed, 269 insertions, 170 deletions
diff --git a/OPS b/OPS
index 2e027983..046ef608 100644
--- a/OPS
+++ b/OPS
@@ -26,6 +26,7 @@ OP_COMPOSE_EDIT_MIME "edit attachment using mailcap entry"
OP_COMPOSE_EDIT_REPLY_TO "edit the Reply-To field"
OP_COMPOSE_EDIT_SUBJECT "edit the subject of this message"
OP_COMPOSE_EDIT_TO "edit the TO list"
+OP_CREATE_MAILBOX "create a new mailbox (IMAP only)"
OP_EDIT_TYPE "edit attachment content type"
OP_COMPOSE_GET_ATTACHMENT "get a temporary copy of an attachment"
OP_COMPOSE_ISPELL "run ispell on the message"
@@ -116,7 +117,6 @@ OP_MAIN_TAG_PATTERN "tag messages matching a pattern"
OP_MAIN_UNDELETE_PATTERN "undelete messages matching a pattern"
OP_MAIN_UNTAG_PATTERN "untag messages matching a pattern"
OP_MIDDLE_PAGE "move to the middle of the page"
-OP_NEW_MAILBOX "create a new mailbox (IMAP only)"
OP_NEXT_ENTRY "move to the next entry"
OP_NEXT_LINE "scroll down one line"
OP_NEXT_PAGE "move to the next page"
diff --git a/browser.c b/browser.c
index 4d76352c..4b8d5631 100644
--- a/browser.c
+++ b/browser.c
@@ -202,18 +202,20 @@ folder_format_str (char *dest, size_t destlen, char op, const char *src,
snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
snprintf (dest, destlen, tmp, permission);
}
- else
- {
#ifdef USE_IMAP
- if (folder->ff->imap)
- {
- /* mark folders with subfolders AND mail */
- sprintf (permission, "IMAP %c",
- (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
- snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
- snprintf (dest, destlen, tmp, permission);
- }
+ else if (folder->ff->imap)
+ {
+ /* mark folders with subfolders AND mail */
+ sprintf (permission, "IMAP %c",
+ (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
+ snprintf (dest, destlen, tmp, permission);
+ }
#endif
+ else
+ {
+ snprintf (tmp, sizeof (tmp), "%%%ss", fmt);
+ snprintf (dest, destlen, tmp, "");
}
break;
@@ -252,8 +254,16 @@ folder_format_str (char *dest, size_t destlen, char op, const char *src,
break;
case 'N':
+#ifdef USE_IMAP
+ if (mx_is_imap (folder->ff->desc))
+ {
+ snprintf (tmp, sizeof (tmp), "%%%sd", fmt);
+ snprintf (dest, destlen, tmp, folder->ff->new);
+ break;
+ }
+#endif
snprintf (tmp, sizeof (tmp), "%%%sc", fmt);
- snprintf (dest, destlen, tmp, folder->ff->is_new ? 'N' : ' ');
+ snprintf (dest, destlen, tmp, folder->ff->new ? 'N' : ' ');
break;
case 's':
@@ -327,7 +337,7 @@ static void add_folder (MUTTMENU *m, struct browser_state *state,
memcpy ((state->entry)[state->entrylen].st, s, sizeof (struct stat));
}
- (state->entry)[state->entrylen].is_new = new;
+ (state->entry)[state->entrylen].new = new;
(state->entry)[state->entrylen].name = safe_strdup (name);
(state->entry)[state->entrylen].desc = safe_strdup (name);
#ifdef USE_IMAP
@@ -815,8 +825,24 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
mutt_ungetch (0, OP_CHECK_NEW);
break;
- case OP_NEW_MAILBOX:
- mutt_error (_("Creating mailboxes is not yet supported."));
+ case OP_CREATE_MAILBOX:
+ if (!state.imap_browse)
+ mutt_error (_("Create is only supported for IMAP mailboxes"));
+ else
+ {
+ imap_mailbox_create (LastDir);
+ /* TODO: find a way to detect if the new folder would appear in
+ * this window, and insert it without starting over. */
+ destroy_state (&state);
+ init_state (&state, NULL);
+ state.imap_browse = 1;
+ imap_browse (LastDir, &state);
+ menu->data = state.entry;
+ menu->current = 0;
+ menu->top = 0;
+ init_menu (&state, menu, title, sizeof (title), buffy);
+ MAYBE_REDRAW (menu->redraw);
+ }
break;
case OP_DELETE_MAILBOX:
@@ -824,7 +850,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
mutt_error (_("Delete is only supported for IMAP mailboxes"));
else
{
- char msg[LONG_STRING];
+ char msg[SHORT_STRING];
IMAP_MBOX mx;
int nentry = menu->current;
@@ -850,6 +876,7 @@ void _mutt_select_file (char *f, size_t flen, int buffy,
}
else
mutt_message _("Mailbox not deleted.");
+ FREE (&mx.mbox);
}
break;
#endif
diff --git a/browser.h b/browser.h
index 7ad9e56e..4f2adda9 100644
--- a/browser.h
+++ b/browser.h
@@ -29,6 +29,8 @@ struct folder_file
char *name;
char *desc;
+
+ unsigned short new;
#ifdef USE_IMAP
char delim;
@@ -37,7 +39,6 @@ struct folder_file
unsigned inferiors : 1;
#endif
unsigned tagged : 1;
- unsigned is_new : 1;
};
struct browser_state
diff --git a/buffy.c b/buffy.c
index cbdf74f1..5ed50a4a 100644
--- a/buffy.c
+++ b/buffy.c
@@ -230,23 +230,11 @@ int mutt_buffy_check (int force)
char path[_POSIX_PATH_MAX];
struct stat contex_sb;
time_t t;
-#ifdef USE_IMAP
- static time_t last_imap_check = 0;
- int do_imap_check = 1;
-
- if (ImapCheckTimeout)
- {
- time_t now = time (NULL);
- if (now - last_imap_check < ImapCheckTimeout)
- do_imap_check = 0;
- else
- last_imap_check = now;
- }
+#ifdef USE_IMAP
/* update postponed count as well, on force */
if (force)
mutt_update_num_postponed ();
-
#endif
/* fastest return if there are no mailboxes */
@@ -272,37 +260,37 @@ int mutt_buffy_check (int force)
for (tmp = Incoming; tmp; tmp = tmp->next)
{
+ tmp->new = 0;
+
#ifdef USE_IMAP
if ((tmp->magic == M_IMAP) || mx_is_imap (tmp->path))
tmp->magic = M_IMAP;
else
#endif
+ if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
+ (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
{
- tmp->new = 0;
-
- if (stat (tmp->path, &sb) != 0 || sb.st_size == 0 ||
- (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0))
- {
- /* if the mailbox still doesn't exist, set the newly created flag to
- * be ready for when it does.
- */
- tmp->newly_created = 1;
- tmp->magic = 0;
+ /* if the mailbox still doesn't exist, set the newly created flag to
+ * be ready for when it does. */
+ tmp->newly_created = 1;
+ tmp->magic = 0;
#ifdef BUFFY_SIZE
- tmp->size = 0;
+ tmp->size = 0;
#endif
- continue;
- }
+ continue;
}
/* check to see if the folder is the currently selected folder
* before polling */
if (!Context || !Context->path ||
#ifdef USE_IMAP
- /* unless folder is an IMAP folder */
- tmp->magic == M_IMAP ||
+ (tmp->magic == M_IMAP && mutt_strcmp (tmp->path, Context->path)) ||
+ (tmp->magic != M_IMAP && (
#endif
sb.st_dev != contex_sb.st_dev || sb.st_ino != contex_sb.st_ino)
+#ifdef USE_IMAP
+ ))
+#endif
{
switch (tmp->magic)
{
@@ -355,22 +343,10 @@ int mutt_buffy_check (int force)
#ifdef USE_IMAP
case M_IMAP:
- /* poll on do_imap_check, else return cached value.
- * If the check is forced (eg on mailbox open), check only current
- * folder */
- if (do_imap_check || (force && Context && Context->path &&
- !mutt_strcmp (Context->path, tmp->path)))
- {
- tmp->new = 0;
- if (imap_mailbox_check (tmp->path, 1) > 0)
- {
- BuffyCount++;
- tmp->new = 1;
- }
- }
- else
- if (tmp->new)
- BuffyCount++;
+ if ((tmp->new = imap_mailbox_check (tmp->path, 1)) > 0)
+ BuffyCount++;
+ else
+ tmp->new = 0;
break;
#endif
diff --git a/doc/manual.sgml.head b/doc/manual.sgml.head
index cf323526..487cf0c3 100644
--- a/doc/manual.sgml.head
+++ b/doc/manual.sgml.head
@@ -2083,11 +2083,17 @@ at only the folders you are subscribed to, or all folders with the
<em/toggle-subscribed/ command. See also the
<ref id="imap&lowbar;list&lowbar;subscribed" name="&dollar;imap&lowbar;list&lowbar;subscribed"> variable.
-Polling for new mail is more expensive over IMAP than locally. For this reason
-the frequency at which Mutt will check for mail remotely can be controlled by
-the
-<ref id="imap&lowbar;checkinterval" name="&dollar;imap&lowbar;checkinterval">
-variable, which defaults to every 60 seconds.
+Polling for new mail on an IMAP server can cause noticeable delays. So, you'll
+want to carefully tune the
+<ref id="mail&lowbar;check" name="&dollar;mail&lowbar;check">
+and
+<ref id="timeout" name="&dollar;timeout">
+variables. Personally I use
+<tscreen><verb>
+set mail_check=90
+set timeout=15
+</verb></tscreen>
+with relatively good results over my slow modem line.
Note that if you are using mbox as the mail store on UW servers prior to
v12.250, the server has been reported to disconnect a client if another client
diff --git a/functions.h b/functions.h
index 60d2fc3e..04993ae5 100644
--- a/functions.h
+++ b/functions.h
@@ -329,7 +329,7 @@ struct binding_t OpBrowser[] = {
{ "toggle-mailboxes", OP_TOGGLE_MAILBOXES, "\t" },
{ "view-file", OP_BROWSER_VIEW_FILE, " " },
#ifdef USE_IMAP
- { "new-mailbox", OP_NEW_MAILBOX, "n" },
+ { "create-mailbox", OP_CREATE_MAILBOX, "C" },
{ "delete-mailbox", OP_DELETE_MAILBOX, "d" },
{ "subscribe", OP_BROWSER_SUBSCRIBE, "s" },
{ "unsubscribe", OP_BROWSER_UNSUBSCRIBE, "u" },
diff --git a/globals.h b/globals.h
index 3fab5fe0..871e59ff 100644
--- a/globals.h
+++ b/globals.h
@@ -51,7 +51,6 @@ WHERE char *Hostname;
#ifdef USE_IMAP
WHERE char *ImapUser INITVAL (NULL);
WHERE char *ImapPass INITVAL (NULL);
-WHERE short ImapCheckTimeout;
WHERE char *ImapHomeNamespace INITVAL (NULL);
#endif
WHERE char *InReplyTo;
diff --git a/imap/browse.c b/imap/browse.c
index cd3b0470..95ef83d6 100644
--- a/imap/browse.c
+++ b/imap/browse.c
@@ -67,22 +67,22 @@ int imap_browse (char* path, struct browser_state* state)
strfcpy (list_cmd, option (OPTIMAPLSUB) ? "LSUB" : "LIST", sizeof (list_cmd));
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
- if (mx.mbox[0] == '\0')
+ if (!mx.mbox)
{
home_namespace = 1;
mbox[0] = '\0'; /* Do not replace "" with "INBOX" here */
- mx.mbox = ImapHomeNamespace;
+ mx.mbox = safe_strdup(ImapHomeNamespace);
nns = 0;
if (mutt_bit_isset(idata->capabilities,NAMESPACE))
{
mutt_message _("Getting namespaces...");
if (browse_get_namespace (idata, nsbuf, sizeof (nsbuf),
nsi, sizeof (nsi), &nns) != 0)
- return -1;
+ goto fail;
if (browse_verify_namespace (idata, nsi, nns) != 0)
- return -1;
+ goto fail;
}
}
@@ -110,7 +110,7 @@ int imap_browse (char* path, struct browser_state* state)
{
if (imap_parse_list_response (idata, &cur_folder, &noselect,
&noinferiors, &idata->delim) != 0)
- return -1;
+ goto fail;
if (cur_folder)
{
@@ -200,14 +200,14 @@ int imap_browse (char* path, struct browser_state* state)
* server to see if it has descendants. */
dprint (4, (debugfile, "imap_init_browse: adding INBOX\n"));
if (browse_add_list_result (idata, "LIST \"\" \"INBOX\"", state, 0))
- return -1;
+ goto fail;
}
nsup = state->entrylen;
snprintf (buf, sizeof (buf), "%s \"\" \"%s%%\"", list_cmd, mbox);
if (browse_add_list_result (idata, buf, state, 0))
- return -1;
+ goto fail;
qsort(&(state->entry[nsup]),state->entrylen-nsup,sizeof(state->entry[0]),
(int (*)(const void*,const void*)) compare_names);
@@ -223,7 +223,60 @@ int imap_browse (char* path, struct browser_state* state)
}
mutt_clear_error ();
+ FREE (&mx.mbox);
+ return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
+}
+
+/* imap_mailbox_create: Prompt for a new mailbox name, and try to create it */
+int imap_mailbox_create (const char* folder)
+{
+ IMAP_DATA* idata;
+ IMAP_MBOX mx;
+ char buf[LONG_STRING];
+ short n;
+
+ if (imap_parse_path (folder, &mx) < 0)
+ {
+ dprint (1, (debugfile, "imap_mailbox_create: Bad starting path %s\n",
+ folder));
+ return -1;
+ }
+
+ if (!(idata = imap_conn_find (&mx.account, M_IMAP_CONN_NONEW)))
+ {
+ dprint (1, (debugfile, "imap_mailbox_create: Couldn't find open connection to %s", mx.account.host));
+ goto fail;
+ }
+
+ strfcpy (buf, NONULL (mx.mbox), sizeof (buf));
+
+ /* append a delimiter if necessary */
+ n = mutt_strlen (buf);
+ if (n && (n < sizeof (buf) - 1) && (buf[n-1] != idata->delim))
+ {
+ buf[n++] = idata->delim;
+ buf[n] = '\0';
+ }
+
+ if (mutt_get_field (_("Create mailbox: "), buf, sizeof (buf), M_FILE) < 0)
+ goto fail;
+
+ if (imap_create_mailbox (idata, buf) < 0)
+ goto fail;
+
+ mutt_message _("Mailbox created.");
+ sleep (1);
+
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
@@ -247,7 +300,10 @@ static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
{
if (imap_parse_list_response(idata, &name, &noselect, &noinferiors,
&idata->delim) != 0)
+ {
+ FREE (&mx.mbox);
return -1;
+ }
if (name)
{
@@ -262,6 +318,7 @@ static int browse_add_list_result (IMAP_DATA* idata, const char* cmd,
}
while ((mutt_strncmp (idata->buf, idata->seq, SEQLEN) != 0));
+ FREE (&mx.mbox);
return 0;
}
@@ -300,7 +357,10 @@ static void imap_add_folder (char delim, char *folder, int noselect,
* than at scan, since it's so expensive to scan. But that's big changes
* to browser.c */
if (!((regexec (Mask.rx, relpath, 0, NULL, 0) == 0) ^ Mask.not))
+ {
+ FREE (&mx.mbox);
return;
+ }
imap_qualify_path (tmp, sizeof (tmp), &mx, folder, NULL);
(state->entry)[state->entrylen].name = safe_strdup (tmp);
@@ -322,6 +382,8 @@ static void imap_add_folder (char delim, char *folder, int noselect,
(state->entry)[state->entrylen].selectable = !noselect;
(state->entry)[state->entrylen].inferiors = !noinferiors;
(state->entrylen)++;
+
+ FREE (&mx.mbox);
}
static int compare_names(struct folder_file *a, struct folder_file *b)
diff --git a/imap/command.c b/imap/command.c
index a406c942..babde98e 100644
--- a/imap/command.c
+++ b/imap/command.c
@@ -242,11 +242,11 @@ static void cmd_finish (IMAP_DATA* idata)
{
/* read new mail messages */
dprint (2, (debugfile, "cmd_finish: Fetching new mail\n"));
- count = imap_read_headers (idata, idata->ctx->msgcount, count-1)+1;
/* check_status: curs_main uses imap_check_mailbox to detect
* whether the index needs updating */
idata->check_status = IMAP_NEWMAIL_PENDING;
idata->reopen &= ~IMAP_NEWMAIL_PENDING;
+ count = imap_read_headers (idata, idata->ctx->msgcount, count-1)+1;
}
else
{
diff --git a/imap/imap.c b/imap/imap.c
index c122df69..e66878ca 100644
--- a/imap/imap.c
+++ b/imap/imap.c
@@ -45,18 +45,15 @@ static int imap_check_capabilities (IMAP_DATA* idata);
static void imap_set_flag (IMAP_DATA* idata, int aclbit, int flag,
const char* str, char* flags);
-int imap_create_mailbox (CONTEXT* ctx, char* mailbox)
+int imap_create_mailbox (IMAP_DATA* idata, char* mailbox)
{
char buf[LONG_STRING], mbox[LONG_STRING];
imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
snprintf (buf, sizeof (buf), "CREATE %s", mbox);
- if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0)
- {
- imap_error ("imap_create_mailbox", CTX_DATA->buf);
+ if (imap_exec (idata, buf, 0) != 0)
return -1;
- }
return 0;
}
@@ -65,14 +62,11 @@ int imap_delete_mailbox (CONTEXT* ctx, char* mailbox)
{
char buf[LONG_STRING], mbox[LONG_STRING];
- imap_quote_string (mbox, sizeof (mbox), mailbox);
+ imap_munge_mbox_name (mbox, sizeof (mbox), mailbox);
snprintf (buf, sizeof (buf), "DELETE %s", mbox);
if (imap_exec ((IMAP_DATA*) ctx->data, buf, 0) != 0)
- {
- imap_error ("imap_delete_mailbox", CTX_DATA->buf);
return -1;
- }
return 0;
}
@@ -475,14 +469,14 @@ int imap_open_mailbox (CONTEXT* ctx)
/* we require a connection which isn't currently in IMAP_SELECTED state */
if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NOSELECT)))
- return -1;
+ goto fail;
conn = idata->conn;
/* once again the context is new */
ctx->data = idata;
if (idata->status == IMAP_FATAL)
- return -1;
+ goto fail;
/* Clean up path and replace the one in the ctx */
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
@@ -537,7 +531,7 @@ int imap_open_mailbox (CONTEXT* ctx)
{
dprint (2, (debugfile, "Getting mailbox FLAGS\n"));
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
- return -1;
+ goto fail;
}
}
/* PERMANENTFLAGS are massaged to look like FLAGS, then override FLAGS */
@@ -549,13 +543,13 @@ int imap_open_mailbox (CONTEXT* ctx)
/* skip "OK [PERMANENT" so syntax is the same as FLAGS */
pc += 13;
if ((pc = imap_get_flags (&(idata->flags), pc)) == NULL)
- return -1;
+ goto fail;
}
}
while (rc == IMAP_CMD_CONTINUE);
if (rc != IMAP_CMD_DONE)
- return -1;
+ goto fail;
/* check for READ-ONLY notification */
if (!strncmp (imap_get_qualifier (idata->buf), "[READ-ONLY]", 11))
@@ -595,13 +589,13 @@ int imap_open_mailbox (CONTEXT* ctx)
mutt_error ("%s", s);
idata->state = IMAP_AUTHENTICATED;
sleep (1);
- return -1;
+ goto fail;
}
if (mutt_bit_isset (idata->capabilities, ACL))
{
if (imap_check_acl (idata))
- return -1;
+ goto fail;
}
/* assume we have all rights if ACL is unavailable */
else
@@ -623,7 +617,12 @@ int imap_open_mailbox (CONTEXT* ctx)
count = imap_read_headers (idata, 0, count - 1) + 1;
dprint (1, (debugfile, "imap_open_mailbox(): msgcount is %d\n", ctx->msgcount));
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
int imap_open_mailbox_append (CONTEXT *ctx)
@@ -642,7 +641,7 @@ int imap_open_mailbox_append (CONTEXT *ctx)
* ctx is brand new and mostly empty */
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
conn = idata->conn;
ctx->magic = M_IMAP;
@@ -665,7 +664,7 @@ int imap_open_mailbox_append (CONTEXT *ctx)
/* STATUS not supported */
mutt_message _("Unable to append to IMAP mailboxes at this server");
- return -1;
+ goto fail;
}
r = imap_exec (idata, buf, IMAP_CMD_FAIL_OK);
@@ -674,16 +673,21 @@ int imap_open_mailbox_append (CONTEXT *ctx)
/* command failed cause folder doesn't exist */
snprintf (buf, sizeof (buf), _("Create %s?"), mailbox);
if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
- return -1;
+ goto fail;
- if (imap_create_mailbox (ctx, mailbox) < 0)
- return -1;
+ if (imap_create_mailbox (idata, mailbox) < 0)
+ goto fail;
}
else if (r == -1)
/* Hmm, some other failure */
- return -1;
+ goto fail;
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_logout: Gracefully log out of server. */
@@ -915,12 +919,12 @@ int imap_sync_mailbox (CONTEXT* ctx, int expunge, int* index_hint)
mutt_remove_trailing_ws (flags);
- snprintf (buf, sizeof (buf), "STORE %d -FLAGS.SILENT (%s)",
- ctx->hdrs[n]->index + 1, flags);
+ snprintf (buf, sizeof (buf), "UID STORE %d -FLAGS.SILENT (%s)",
+ HEADER_DATA (ctx->hdrs[n])->uid, flags);
}
else
- snprintf (buf, sizeof (buf), "STORE %d FLAGS.SILENT (%s)",
- ctx->hdrs[n]->index + 1, flags);
+ snprintf (buf, sizeof (buf), "UID STORE %d FLAGS.SILENT (%s)",
+ HEADER_DATA (ctx->hdrs[n])->uid, flags);
/* after all this it's still possible to have no flags, if you
* have no ACL rights */
@@ -964,15 +968,14 @@ void imap_close_mailbox (CONTEXT* ctx)
if (!idata)
return;
- idata->reopen &= IMAP_REOPEN_ALLOW;
-
if ((idata->status != IMAP_FATAL) &&
(idata->state == IMAP_SELECTED) &&
(ctx == idata->ctx))
{
if (!(idata->noclose) && imap_exec (idata, "CLOSE", 0))
imap_error ("CLOSE failed", idata->buf);
-
+
+ idata->reopen &= IMAP_REOPEN_ALLOW;
idata->state = IMAP_AUTHENTICATED;
FREE (&(idata->mailbox));
}
@@ -1001,45 +1004,33 @@ void imap_close_mailbox (CONTEXT* ctx)
*/
int imap_check_mailbox (CONTEXT *ctx, int *index_hint)
{
- static time_t checktime=0;
+ /* overload keyboard timeout to avoid many mailbox checks in a row.
+ * Most users don't like having to wait exactly when they press a key. */
+ static time_t LastCheck = 0;
IMAP_DATA* idata;
- time_t t = 0;
+ time_t now;
idata = (IMAP_DATA*) ctx->data;
- /*
- * gcc thinks it has to warn about uninitialized use
- * of t. This is wrong.
- */
-
- if (ImapCheckTimeout)
- {
- t = time(NULL);
- t -= checktime;
- }
-
- /* TODO: wtf?! */
- if ((ImapCheckTimeout && t >= ImapCheckTimeout)
- || ((idata->reopen & IMAP_REOPEN_ALLOW) && (idata->reopen & ~IMAP_REOPEN_ALLOW)))
- {
- if (ImapCheckTimeout) checktime += t;
+ now = time(NULL);
+ if (now > LastCheck + Timeout) {
+ LastCheck = now;
if (imap_exec (idata, "NOOP", 0) != 0)
{
imap_error ("imap_check_mailbox", idata->buf);
return -1;
}
+ }
- if (idata->check_status & IMAP_NEWMAIL_PENDING)
- {
- idata->check_status &= ~IMAP_NEWMAIL_PENDING;
- return M_NEW_MAIL;
- }
-
- /* TODO: we should be able to detect external changes and return
- * M_REOPENED here. */
+ if (idata->check_status & IMAP_NEWMAIL_PENDING)
+ {
+ idata->check_status &= ~IMAP_NEWMAIL_PENDING;
+ return M_NEW_MAIL;
}
+ /* TODO: we should be able to detect external changes and return
+ * M_REOPENED here. */
return 0;
}
@@ -1071,7 +1062,7 @@ int imap_mailbox_check (char* path, int new)
connflags = M_IMAP_CONN_NONEW;
if (!(idata = imap_conn_find (&(mx.account), connflags)))
- return -1;
+ goto fail;
conn = idata->conn;
imap_fix_path (idata, mx.mbox, buf, sizeof (buf));
@@ -1099,11 +1090,9 @@ int imap_mailbox_check (char* path, int new)
new ? "RECENT" : "MESSAGES");
}
else
- {
/* Server does not support STATUS, and this is not the current mailbox.
* There is no lightweight way to check recent arrivals */
- return -1;
- }
+ goto fail;
imap_cmd_start (idata, buf);
@@ -1128,8 +1117,8 @@ int imap_mailbox_check (char* path, int new)
{
if (*s != '0')
{
- dprint (1, (debugfile, "Mail in %s\n", path));
msgcount = atoi(s);
+ dprint (2, (debugfile, "%d new messages in %s\n", msgcount, path));
}
}
}
@@ -1139,7 +1128,12 @@ int imap_mailbox_check (char* path, int new)
}
while (rc == IMAP_CMD_CONTINUE);
+ FREE (&mx.mbox);
return msgcount;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* all this listing/browsing is a mess. I don't like that name is a pointer
@@ -1227,7 +1221,7 @@ int imap_subscribe (char *path, int subscribe)
return -1;
if (!(idata = imap_conn_find (&(mx.account), 0)))
- return -1;
+ goto fail;
conn = idata->conn;
@@ -1242,9 +1236,14 @@ int imap_subscribe (char *path, int subscribe)
"UNSUBSCRIBE", mbox);
if (imap_exec (idata, buf, 0) < 0)
- return -1;
+ goto fail;
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_complete: given a partial IMAP folder path, return a string which
@@ -1272,7 +1271,7 @@ int imap_complete(char* dest, size_t dlen, char* path) {
/* don't open a new socket just for completion */
if (!(idata = imap_conn_find (&(mx.account), M_IMAP_CONN_NONEW)))
- return -1;
+ goto fail;
conn = idata->conn;
/* reformat path for IMAP list, and append wildcard */
@@ -1336,8 +1335,11 @@ int imap_complete(char* dest, size_t dlen, char* path) {
imap_qualify_path (dest, dlen, &mx, completion, NULL);
mutt_pretty_mailbox (dest);
+ FREE (&mx.mbox);
return 0;
}
+ fail:
+ FREE (&mx.mbox);
return -1;
}
diff --git a/imap/imap.h b/imap/imap.h
index 99eaacaa..1e26941e 100644
--- a/imap/imap.h
+++ b/imap/imap.h
@@ -32,7 +32,6 @@ typedef struct
/* imap.c */
int imap_check_mailbox (CONTEXT *ctx, int *index_hint);
-int imap_create_mailbox (CONTEXT* idata, char* mailbox);
int imap_close_connection (CONTEXT *ctx);
int imap_delete_mailbox (CONTEXT* idata, char* mailbox);
int imap_open_mailbox (CONTEXT *ctx);
@@ -49,6 +48,7 @@ void imap_disallow_reopen (CONTEXT *ctx);
/* browse.c */
int imap_browse (char* path, struct browser_state* state);
+int imap_mailbox_create (const char* folder);
/* message.c */
int imap_append_message (CONTEXT* ctx, MESSAGE* msg);
diff --git a/imap/imap_private.h b/imap/imap_private.h
index b574ee81..9611890e 100644
--- a/imap/imap_private.h
+++ b/imap/imap_private.h
@@ -44,7 +44,7 @@
#define SEQLEN 5
#define IMAP_REOPEN_ALLOW (1<<0)
-#define IMAP_EXPUNGE_PENDING (1<<1)
+#define IMAP_EXPUNGE_PENDING (1<<1)
#define IMAP_NEWMAIL_PENDING (1<<2)
/* imap_exec flags (see imap_exec) */
@@ -172,6 +172,7 @@ typedef struct
/* -- private IMAP functions -- */
/* imap.c */
+int imap_create_mailbox (IMAP_DATA* idata, char* mailbox);
int imap_make_msg_set (IMAP_DATA* idata, char* buf, size_t buflen, int flag,
int changed);
int imap_open_connection (IMAP_DATA* idata);
diff --git a/imap/message.c b/imap/message.c
index ad25e918..9db78bb1 100644
--- a/imap/message.c
+++ b/imap/message.c
@@ -192,6 +192,7 @@ int imap_read_headers (IMAP_DATA* idata, int msgbegin, int msgend)
int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
{
IMAP_DATA* idata;
+ HEADER* h;
char buf[LONG_STRING];
char path[_POSIX_PATH_MAX];
char *pc;
@@ -293,9 +294,10 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
!ctx->hdrs[msgno]->changed)
{
IMAP_HEADER newh;
- HEADER* h = ctx->hdrs[msgno];
unsigned char readonly;
+ h = ctx->hdrs[msgno];
+
memset (&newh, 0, sizeof (newh));
newh.data = safe_calloc (1, sizeof (IMAP_HEADER_DATA));
@@ -348,23 +350,37 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno)
/* Update the header information. Previously, we only downloaded a
* portion of the headers, those required for the main display.
*/
+ h = ctx->hdrs[msgno];
rewind (msg->fp);
- mutt_free_envelope (&ctx->hdrs[msgno]->env);
- ctx->hdrs[msgno]->env = mutt_read_rfc822_header (msg->fp, ctx->hdrs[msgno],0, 0);
- ctx->hdrs[msgno]->lines = 0;
+ /* I hate do this here, since it's so low-level, but I'm not sure where
+ * I can abstract it. Problem: the id and subj hashes lose their keys when
+ * mutt_free_envelope gets called, but keep their spots in the hash. This
+ * confuses threading. Alternatively we could try to merge the new
+ * envelope into the old one. Also messy and lowlevel. */
+ if (h->env->message_id)
+ hash_delete (ctx->id_hash, h->env->message_id, h, NULL);
+ if (h->env->real_subj)
+ hash_delete (ctx->subj_hash, h->env->real_subj, h, NULL);
+ mutt_free_envelope (&h->env);
+ h->env = mutt_read_rfc822_header (msg->fp, h, 0, 0);
+ if (h->env->message_id)
+ hash_insert (ctx->id_hash, h->env->message_id, h, 0);
+ if (h->env->real_subj)
+ hash_insert (ctx->subj_hash, h->env->real_subj, h, 1);
+
+ h->lines = 0;
fgets (buf, sizeof (buf), msg->fp);
while (!feof (msg->fp))
{
- ctx->hdrs[msgno]->lines++;
+ h->lines++;
fgets (buf, sizeof (buf), msg->fp);
}
- ctx->hdrs[msgno]->content->length = ftell (msg->fp) -
- ctx->hdrs[msgno]->content->offset;
+ h->content->length = ftell (msg->fp) - h->content->offset;
/* This needs to be done in case this is a multipart message */
#ifdef HAVE_PGP
- ctx->hdrs[msgno]->pgp = pgp_query (ctx->hdrs[msgno]->content);
+ h->pgp = pgp_query (h->content);
#endif /* HAVE_PGP */
mutt_clear_error();
@@ -405,7 +421,7 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
if ((fp = fopen (msg->path, "r")) == NULL)
{
mutt_perror (msg->path);
- return (-1);
+ goto fail;
}
for (last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c)
@@ -438,7 +454,7 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
mutt_error ("%s", pc);
sleep (1);
fclose (fp);
- return (-1);
+ goto fail;
}
mutt_message _("Uploading message ...");
@@ -474,10 +490,15 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg)
pc = imap_next_word (pc);
mutt_error ("%s", pc);
sleep (1);
- return (-1);
+ goto fail;
}
+ FREE (&mx.mbox);
return 0;
+
+ fail:
+ FREE (&mx.mbox);
+ return -1;
}
/* imap_copy_messages: use server COPY command to copy messages to another
@@ -510,7 +531,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
{
dprint (3, (debugfile, "imap_copy_message: %s not same server as %s\n",
dest, ctx->path));
- return 1;
+ goto fail;
}
imap_fix_path (idata, mx.mbox, cmd, sizeof (cmd));
@@ -522,7 +543,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
if (!rc)
{
dprint (1, (debugfile, "imap_copy_messages: No messages tagged\n"));
- return -1;
+ goto fail;
}
mutt_message (_("Copying %d messages to %s..."), rc, cmd);
}
@@ -543,17 +564,17 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
if (strncmp (imap_get_qualifier (idata->buf), "[TRYCREATE]", 11))
{
imap_error ("imap_copy_messages", idata->buf);
- return -1;
+ goto fail;
}
dprint (2, (debugfile, "imap_copy_messages: server suggests TRYCREATE\n"));
snprintf (buf, sizeof (buf), _("Create %s?"), mbox);
if (option (OPTCONFIRMCREATE) && mutt_yesorno (buf, 1) < 1)
{
mutt_clear_error ();
- return -1;
+ goto fail;
}
- if (imap_create_mailbox (ctx, mbox) < 0)
- return -1;
+ if (imap_create_mailbox (idata, mbox) < 0)
+ goto fail;
/* try again */
rc = imap_exec (idata, cmd, 0);
@@ -561,7 +582,7 @@ int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
if (rc != 0)
{
imap_error ("imap_copy_messages", idata-&