Re: IMAP status flags lost when refiling
On Sat, Apr 02, 2005 at 11:13:49AM -0500, Daniel Jacobowitz wrote:
> If you're going to do that, might as well set the flags on the message
> before it is copied :-) I'll give it a try.
Like so. It appears to work. Not the most elegant code I've ever
written though.
--
Daniel Jacobowitz
CodeSourcery, LLC
Index: mutt/imap/message.c
===================================================================
--- mutt.orig/imap/message.c 2005-04-02 11:21:13.000000000 -0500
+++ mutt/imap/message.c 2005-04-02 12:16:26.000000000 -0500
@@ -640,13 +640,14 @@ int imap_append_message (CONTEXT *ctx, M
int imap_copy_messages (CONTEXT* ctx, HEADER* h, char* dest, int delete)
{
IMAP_DATA* idata;
- BUFFER cmd;
+ BUFFER cmd, sync_cmd;
char uid[11];
char mbox[LONG_STRING];
char mmbox[LONG_STRING];
int rc;
int n;
IMAP_MBOX mx;
+ int err_continue = M_NO;
idata = (IMAP_DATA*) ctx->data;
@@ -672,6 +673,7 @@ int imap_copy_messages (CONTEXT* ctx, HE
imap_fix_path (idata, mx.mbox, mbox, sizeof (mbox));
+ memset (&sync_cmd, 0, sizeof (sync_cmd));
memset (&cmd, 0, sizeof (cmd));
mutt_buffer_addstr (&cmd, "UID COPY ");
@@ -688,6 +690,17 @@ int imap_copy_messages (CONTEXT* ctx, HE
dprint (3, (debugfile, "imap_copy_messages: Message contains
attachments to be deleted\n"));
return 1;
}
+
+ if (ctx->hdrs[n]->tagged && ctx->hdrs[n]->active &&
+ ctx->hdrs[n]->changed)
+ {
+ rc = imap_sync_message (idata, ctx->hdrs[n], &sync_cmd, &err_continue);
+ if (rc < 0)
+ {
+ dprint (1, (debugfile, "imap_copy_messages: could not sync\n"));
+ goto fail;
+ }
+ }
}
rc = imap_make_msg_set (idata, &cmd, M_TAG, 0);
@@ -703,6 +716,16 @@ int imap_copy_messages (CONTEXT* ctx, HE
mutt_message (_("Copying message %d to %s..."), h->index+1, mbox);
snprintf (uid, sizeof (uid), "%u", HEADER_DATA (h)->uid);
mutt_buffer_addstr (&cmd, uid);
+
+ if (h->active && h->changed)
+ {
+ rc = imap_sync_message (idata, h, &sync_cmd, &err_continue);
+ if (rc < 0)
+ {
+ dprint (1, (debugfile, "imap_copy_messages: could not sync\n"));
+ goto fail;
+ }
+ }
}
/* let's get it on */
@@ -761,12 +784,16 @@ int imap_copy_messages (CONTEXT* ctx, HE
if (cmd.data)
FREE (&cmd.data);
+ if (sync_cmd.data)
+ FREE (&sync_cmd.data);
FREE (&mx.mbox);
return 0;
fail:
if (cmd.data)
FREE (&cmd.data);
+ if (sync_cmd.data)
+ FREE (&sync_cmd.data);
FREE (&mx.mbox);
return -1;
}
Index: mutt/imap/imap.c
===================================================================
--- mutt.orig/imap/imap.c 2005-04-02 11:15:28.000000000 -0500
+++ mutt/imap/imap.c 2005-04-02 12:17:41.000000000 -0500
@@ -921,6 +921,74 @@ int imap_make_msg_set (IMAP_DATA* idata,
return count;
}
+/* 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)
+{
+ char flags[LONG_STRING];
+ char uid[11];
+
+ hdr->changed = 0;
+
+ snprintf (uid, sizeof (uid), "%u", HEADER_DATA(hdr)->uid);
+ cmd->dptr = cmd->data;
+ mutt_buffer_addstr (cmd, "UID STORE ");
+ mutt_buffer_addstr (cmd, uid);
+
+ flags[0] = '\0';
+
+ imap_set_flag (idata, IMAP_ACL_SEEN, hdr->read, "\\Seen ",
+ flags, sizeof (flags));
+ imap_set_flag (idata, IMAP_ACL_WRITE, hdr->flagged,
+ "\\Flagged ", flags, sizeof (flags));
+ imap_set_flag (idata, IMAP_ACL_WRITE, hdr->replied,
+ "\\Answered ", flags, sizeof (flags));
+ imap_set_flag (idata, IMAP_ACL_DELETE, hdr->deleted,
+ "\\Deleted ", flags, sizeof (flags));
+
+ /* now make sure we don't lose custom tags */
+ if (mutt_bit_isset (idata->rights, IMAP_ACL_WRITE))
+ imap_add_keywords (flags, hdr, idata->flags, sizeof (flags));
+
+ mutt_remove_trailing_ws (flags);
+
+ /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
+ * explicitly revoke all system flags (if we have permission) */
+ if (!*flags)
+ {
+ imap_set_flag (idata, IMAP_ACL_SEEN, 1, "\\Seen ", flags, sizeof (flags));
+ imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Flagged ", flags, sizeof
(flags));
+ imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Answered ", flags, sizeof
(flags));
+ imap_set_flag (idata, IMAP_ACL_DELETE, 1, "\\Deleted ", flags, sizeof
(flags));
+
+ mutt_remove_trailing_ws (flags);
+
+ mutt_buffer_addstr (cmd, " -FLAGS.SILENT (");
+ } else
+ mutt_buffer_addstr (cmd, " FLAGS.SILENT (");
+
+ mutt_buffer_addstr (cmd, flags);
+ mutt_buffer_addstr (cmd, ")");
+
+ /* dumb hack for bad UW-IMAP 4.7 servers spurious FLAGS updates */
+ hdr->active = 0;
+
+ /* after all this it's still possible to have no flags, if you
+ * have no ACL rights */
+ if (*flags && (imap_exec (idata, cmd->data, 0) != 0) &&
+ err_continue && (*err_continue != M_YES))
+ {
+ *err_continue = imap_continue ("imap_sync_mailbox: STORE failed",
+ idata->cmd.buf);
+ if (*err_continue != M_YES)
+ return -1;
+ }
+
+ hdr->active = 1;
+ return 0;
+}
+
/* update the IMAP server to reflect message changes done within mutt.
* Arguments
* ctx: the current context
@@ -932,12 +1000,10 @@ int imap_sync_mailbox (CONTEXT* ctx, int
IMAP_DATA* idata;
CONTEXT* appendctx = NULL;
BUFFER cmd;
- char flags[LONG_STRING];
- char uid[11];
int deleted;
int n;
- int err_continue = M_NO; /* continue on error? */
int rc;
+ int err_continue = M_NO; /* continue on error? */
idata = (IMAP_DATA*) ctx->data;
@@ -994,84 +1060,29 @@ int imap_sync_mailbox (CONTEXT* ctx, int
{
if (ctx->hdrs[n]->active && ctx->hdrs[n]->changed)
{
- ctx->hdrs[n]->changed = 0;
-
mutt_message (_("Saving message status flags... [%d/%d]"), n+1,
ctx->msgcount);
- snprintf (uid, sizeof (uid), "%u", HEADER_DATA(ctx->hdrs[n])->uid);
- cmd.dptr = cmd.data;
- mutt_buffer_addstr (&cmd, "UID STORE ");
- mutt_buffer_addstr (&cmd, uid);
-
/* if attachments have been deleted we delete the message and reupload
* it. This works better if we're expunging, of course. */
if (ctx->hdrs[n]->attach_del)
- {
- dprint (3, (debugfile, "imap_sync_mailbox: Attachments to be deleted,
falling back to _mutt_save_message\n"));
- 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"));
+ dprint (3, (debugfile, "imap_sync_mailbox: Attachments to be deleted,
falling back to _mutt_save_message\n"));
+ 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 (ctx->hdrs[n], appendctx, 1, 0, 0);
}
- else
- _mutt_save_message (ctx->hdrs[n], appendctx, 1, 0, 0);
- }
- flags[0] = '\0';
-
- imap_set_flag (idata, IMAP_ACL_SEEN, ctx->hdrs[n]->read, "\\Seen ",
- flags, sizeof (flags));
- imap_set_flag (idata, IMAP_ACL_WRITE, ctx->hdrs[n]->flagged,
- "\\Flagged ", flags, sizeof (flags));
- imap_set_flag (idata, IMAP_ACL_WRITE, ctx->hdrs[n]->replied,
- "\\Answered ", flags, sizeof (flags));
- imap_set_flag (idata, IMAP_ACL_DELETE, ctx->hdrs[n]->deleted,
- "\\Deleted ", flags, sizeof (flags));
-
- /* now make sure we don't lose custom tags */
- if (mutt_bit_isset (idata->rights, IMAP_ACL_WRITE))
- imap_add_keywords (flags, ctx->hdrs[n], idata->flags, sizeof (flags));
-
- mutt_remove_trailing_ws (flags);
-
- /* UW-IMAP is OK with null flags, Cyrus isn't. The only solution is to
- * explicitly revoke all system flags (if we have permission) */
- if (!*flags)
- {
- imap_set_flag (idata, IMAP_ACL_SEEN, 1, "\\Seen ", flags, sizeof
(flags));
- imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Flagged ", flags, sizeof
(flags));
- imap_set_flag (idata, IMAP_ACL_WRITE, 1, "\\Answered ", flags, sizeof
(flags));
- imap_set_flag (idata, IMAP_ACL_DELETE, 1, "\\Deleted ", flags, sizeof
(flags));
-
- mutt_remove_trailing_ws (flags);
- mutt_buffer_addstr (&cmd, " -FLAGS.SILENT (");
- }
- else
- mutt_buffer_addstr (&cmd, " FLAGS.SILENT (");
-
- mutt_buffer_addstr (&cmd, flags);
- mutt_buffer_addstr (&cmd, ")");
-
- /* dumb hack for bad UW-IMAP 4.7 servers spurious FLAGS updates */
- ctx->hdrs[n]->active = 0;
-
- /* after all this it's still possible to have no flags, if you
- * have no ACL rights */
- if (*flags && (imap_exec (idata, cmd.data, 0) != 0) &&
- (err_continue != M_YES))
- {
- err_continue = imap_continue ("imap_sync_mailbox: STORE failed",
- idata->cmd.buf);
- if (err_continue != M_YES)
+ if (imap_sync_message (idata, ctx->hdrs[n], &cmd, &err_continue) < 0)
{
rc = -1;
goto out;
}
- }
-
- ctx->hdrs[n]->active = 1;
}
}
ctx->changed = 0;
Index: mutt/imap/imap_private.h
===================================================================
--- mutt.orig/imap/imap_private.h 2005-04-02 11:15:00.000000000 -0500
+++ mutt/imap/imap_private.h 2005-04-02 12:18:36.000000000 -0500
@@ -203,6 +203,8 @@ int imap_parse_list_response(IMAP_DATA*
int imap_read_literal (FILE* fp, IMAP_DATA* idata, long bytes);
void imap_expunge_mailbox (IMAP_DATA* idata);
void imap_logout (IMAP_DATA* idata);
+int imap_sync_message (IMAP_DATA *idata, HEADER *hdr, BUFFER *cmd,
+ int *err_continue);
/* auth.c */
int imap_authenticate (IMAP_DATA* idata);