commit e565d08246205e30f2cc7af169a52be14d765898
Author: Oswald Buddenhagen <o...@users.sf.net>
Date:   Wed Jan 8 18:22:48 2020 +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        | 25 +++++++++++++++++++++++--
 4 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/src/driver.h b/src/driver.h
index a4fc7a1..238819d 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. */
        int (*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 7bc88f6..76c0e3d 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 */
        list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
        string_list_t *boxes; // _list results
@@ -1199,6 +1200,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;
 }
@@ -2432,6 +2454,14 @@ imap_get_uidnext( store_t *gctx )
        return ctx->uidnext;
 }
 
+static xint
+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
@@ -3433,6 +3463,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 d8c41c5..7582008 100644
--- a/src/drv_maildir.c
+++ b/src/drv_maildir.c
@@ -1325,6 +1325,12 @@ maildir_get_uidnext( store_t *gctx ATTR_UNUSED )
        return 0;
 }
 
+static xint
+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 )
@@ -1934,6 +1940,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 c637af4..e6c89cb 100644
--- a/src/sync.c
+++ b/src/sync.c
@@ -170,6 +170,7 @@ typedef struct {
        uint newuidval[2];  // UID validity obtained from driver
        uint newuid[2];     // TUID lookup makes sense only for UIDs >= this
        uint mmaxxuid;      // highest expired UID on master
+       uchar good_flags[2], bad_flags[2];
 } sync_vars_t;
 
 static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; }
@@ -282,6 +283,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;
@@ -421,7 +440,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;
@@ -1490,6 +1509,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] = 
(uchar)svars->drv[t]->get_supported_flags( svars->ctx[t] );
 
        debug( "synchronizing old entries\n" );
        for (srec = svars->srecs; srec; srec = srec->next) {
@@ -1550,7 +1571,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

Reply via email to