commit ea33942a0968460327f737c37f2a93e0a982aa0f Author: Oswald Buddenhagen <o...@users.sf.net> 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 isync-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/isync-devel