commit ea33942a0968460327f737c37f2a93e0a982aa0f
Author: Oswald Buddenhagen <[email protected]>
Date: Mon Nov 25 17:49:18 2019 +0100
don't try to propagate flags the target store does not support
$Forwarded is not standard, so it will most likely fail with mailboxes
that do not support keywords.
amends c4d7f018.
src/driver.h | 3 +++
src/drv_imap.c | 31 +++++++++++++++++++++++++++++++
src/drv_maildir.c | 7 +++++++
src/sync.c | 26 +++++++++++++++++++++++---
4 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/src/driver.h b/src/driver.h
index d40e5f0..11cc9ba 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -181,6 +181,9 @@ struct driver {
/* Return the minimal UID the next stored message will have. */
uint (*get_uidnext)( store_t *ctx );
+ /* Return the flags that can be stored in the selected mailbox. */
+ xint (*get_supported_flags)( store_t *ctx );
+
/* Confirm that the open mailbox is empty. */
int (*confirm_box_empty)( store_t *ctx );
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 53c43a8..bb32170 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -105,6 +105,7 @@ struct imap_store {
/* trash folder's existence is not confirmed yet */
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
uint got_namespace:1;
+ uint has_forwarded:1;
char delimiter[2]; /* hierarchy delimiter */
char *ns_prefix, ns_delimiter; /* NAMESPACE info */
string_list_t *boxes; // _list results
@@ -1238,6 +1239,27 @@ parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd,
char *s )
error( "IMAP error: malformed APPENDUID status\n" );
return RESP_CANCEL;
}
+ } else if (!strcmp( "PERMANENTFLAGS", arg )) {
+ parse_list_init( &ctx->parse_list_sts );
+ if (parse_imap_list( NULL, &s, &ctx->parse_list_sts ) !=
LIST_OK) {
+ error( "IMAP error: malformed PERMANENTFLAGS status\n"
);
+ return RESP_CANCEL;
+ }
+ int ret = RESP_OK;
+ for (list_t *tmp = ctx->parse_list_sts.head->child; tmp; tmp =
tmp->next) {
+ if (!is_atom( tmp )) {
+ error( "IMAP error: malformed PERMANENTFLAGS
status item\n" );
+ ret = RESP_CANCEL;
+ break;
+ }
+ if (!strcmp( tmp->val, "\\*" ) || !strcmp( tmp->val,
"$Forwarded" )) {
+ ctx->has_forwarded = 1;
+ break;
+ }
+ }
+ free_list( ctx->parse_list_sts.head );
+ ctx->parse_list_sts.head = NULL;
+ return ret;
}
return RESP_OK;
}
@@ -2485,6 +2507,14 @@ imap_get_uidnext( store_t *gctx )
return ctx->uidnext;
}
+static uint
+imap_get_supported_flags( store_t *gctx )
+{
+ imap_store_t *ctx = (imap_store_t *)gctx;
+
+ return ctx->has_forwarded ? 255 : (255 & ~F_FORWARDED);
+}
+
/******************* imap_create_box *******************/
static void
@@ -3493,6 +3523,7 @@ struct driver imap_driver = {
imap_create_box,
imap_open_box,
imap_get_uidnext,
+ imap_get_supported_flags,
imap_confirm_box_empty,
imap_delete_box,
imap_finish_delete_box,
diff --git a/src/drv_maildir.c b/src/drv_maildir.c
index 95eefee..04f871a 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1333,6 +1333,12 @@ maildir_get_uidnext( store_t *gctx ATTR_UNUSED )
return 0;
}
+static uint
+maildir_get_supported_flags( store_t *gctx ATTR_UNUSED )
+{
+ return 255;
+}
+
static void
maildir_create_box( store_t *gctx,
void (*cb)( int sts, void *aux ), void *aux )
@@ -1945,6 +1951,7 @@ struct driver maildir_driver = {
maildir_create_box,
maildir_open_box,
maildir_get_uidnext,
+ maildir_get_supported_flags,
maildir_confirm_box_empty,
maildir_delete_box,
maildir_finish_delete_box,
diff --git a/src/sync.c b/src/sync.c
index cbd3c83..e43d852 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -164,7 +164,7 @@ typedef struct {
message_t *msgs[2], *new_msgs[2];
uint_array_alloc_t trashed_msgs[2];
int state[2], lfd, ret, existing, replayed;
- uint ref_count, nsrecs, opts[2];
+ uint ref_count, nsrecs, opts[2], good_flags[2], bad_flags[2];
uint new_pending[2], flags_pending[2], trash_pending[2];
uint maxuid[2]; // highest UID that was already propagated
uint newmaxuid[2]; // highest UID that is currently being propagated
@@ -286,6 +286,24 @@ match_tuids( sync_vars_t *svars, int t, message_t *msgs )
}
+static uchar
+sanitize_flags( uchar tflags, sync_vars_t *svars, int t )
+{
+ if (!(DFlags & QUIET)) {
+ // We complain only once per flag per store - even though
_theoretically_
+ // each mailbox can support different flags according to the
IMAP spec.
+ uchar bflags = tflags & ~(svars->good_flags[t] |
svars->bad_flags[t]);
+ if (bflags) {
+ char bfbuf[16];
+ make_flags( bflags, bfbuf );
+ notice( "Notice: %s does not support flag(s) '%s'; not
propagating.\n", str_ms[t], bfbuf );
+ svars->bad_flags[t] |= bflags;
+ }
+ }
+ return tflags & svars->good_flags[t];
+}
+
+
typedef struct copy_vars {
void (*cb)( int sts, uint uid, struct copy_vars *vars );
void *aux;
@@ -425,7 +443,7 @@ msg_fetched( int sts, void *aux )
return;
}
- vars->msg->flags = vars->data.flags;
+ vars->msg->flags = vars->data.flags = sanitize_flags(
vars->data.flags, svars, t );
scr = (svars->drv[1-t]->get_caps( svars->ctx[1-t] ) / DRV_CRLF)
& 1;
tcr = (svars->drv[t]->get_caps( svars->ctx[t] ) / DRV_CRLF) & 1;
@@ -1497,6 +1515,8 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int
recent_msgs, void *aux
}
info( "Synchronizing...\n" );
+ for (t = 0; t < 2; t++)
+ svars->good_flags[t] = svars->drv[t]->get_supported_flags(
svars->ctx[t] );
debug( "synchronizing old entries\n" );
for (srec = svars->srecs; srec; srec = srec->next) {
@@ -1557,7 +1577,7 @@ box_loaded( int sts, message_t *msgs, int total_msgs, int
recent_msgs, void *aux
} else {
// We have a source. The target may be
in an unknown state.
if (svars->chan->ops[t] & OP_FLAGS) {
- sflags = srec->msg[1-t]->flags;
+ sflags = sanitize_flags(
srec->msg[1-t]->flags, svars, t );
if ((t == M) && (srec->status &
(S_EXPIRE|S_EXPIRED))) {
/* Don't propagate
deletion resulting from expiration. */
debug( " slave
expiring\n" );
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel