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
.
This commit is contained in:
parent
e8caaaaf65
commit
e565d08246
|
@ -181,6 +181,9 @@ struct driver {
|
||||||
/* Return the minimal UID the next stored message will have. */
|
/* Return the minimal UID the next stored message will have. */
|
||||||
int (*get_uidnext)( store_t *ctx );
|
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. */
|
/* Confirm that the open mailbox is empty. */
|
||||||
int (*confirm_box_empty)( store_t *ctx );
|
int (*confirm_box_empty)( store_t *ctx );
|
||||||
|
|
||||||
|
|
|
@ -105,6 +105,7 @@ struct imap_store {
|
||||||
/* trash folder's existence is not confirmed yet */
|
/* trash folder's existence is not confirmed yet */
|
||||||
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
|
enum { TrashUnknown, TrashChecking, TrashKnown } trashnc;
|
||||||
uint got_namespace:1;
|
uint got_namespace:1;
|
||||||
|
uint has_forwarded:1;
|
||||||
char delimiter[2]; /* hierarchy delimiter */
|
char delimiter[2]; /* hierarchy delimiter */
|
||||||
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
|
list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */
|
||||||
string_list_t *boxes; // _list results
|
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" );
|
error( "IMAP error: malformed APPENDUID status\n" );
|
||||||
return RESP_CANCEL;
|
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;
|
return RESP_OK;
|
||||||
}
|
}
|
||||||
|
@ -2432,6 +2454,14 @@ imap_get_uidnext( store_t *gctx )
|
||||||
return ctx->uidnext;
|
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 *******************/
|
/******************* imap_create_box *******************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -3433,6 +3463,7 @@ struct driver imap_driver = {
|
||||||
imap_create_box,
|
imap_create_box,
|
||||||
imap_open_box,
|
imap_open_box,
|
||||||
imap_get_uidnext,
|
imap_get_uidnext,
|
||||||
|
imap_get_supported_flags,
|
||||||
imap_confirm_box_empty,
|
imap_confirm_box_empty,
|
||||||
imap_delete_box,
|
imap_delete_box,
|
||||||
imap_finish_delete_box,
|
imap_finish_delete_box,
|
||||||
|
|
|
@ -1325,6 +1325,12 @@ maildir_get_uidnext( store_t *gctx ATTR_UNUSED )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static xint
|
||||||
|
maildir_get_supported_flags( store_t *gctx ATTR_UNUSED )
|
||||||
|
{
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
maildir_create_box( store_t *gctx,
|
maildir_create_box( store_t *gctx,
|
||||||
void (*cb)( int sts, void *aux ), void *aux )
|
void (*cb)( int sts, void *aux ), void *aux )
|
||||||
|
@ -1934,6 +1940,7 @@ struct driver maildir_driver = {
|
||||||
maildir_create_box,
|
maildir_create_box,
|
||||||
maildir_open_box,
|
maildir_open_box,
|
||||||
maildir_get_uidnext,
|
maildir_get_uidnext,
|
||||||
|
maildir_get_supported_flags,
|
||||||
maildir_confirm_box_empty,
|
maildir_confirm_box_empty,
|
||||||
maildir_delete_box,
|
maildir_delete_box,
|
||||||
maildir_finish_delete_box,
|
maildir_finish_delete_box,
|
||||||
|
|
25
src/sync.c
25
src/sync.c
|
@ -170,6 +170,7 @@ typedef struct {
|
||||||
uint newuidval[2]; // UID validity obtained from driver
|
uint newuidval[2]; // UID validity obtained from driver
|
||||||
uint newuid[2]; // TUID lookup makes sense only for UIDs >= this
|
uint newuid[2]; // TUID lookup makes sense only for UIDs >= this
|
||||||
uint mmaxxuid; // highest expired UID on master
|
uint mmaxxuid; // highest expired UID on master
|
||||||
|
uchar good_flags[2], bad_flags[2];
|
||||||
} sync_vars_t;
|
} sync_vars_t;
|
||||||
|
|
||||||
static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; }
|
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 {
|
typedef struct copy_vars {
|
||||||
void (*cb)( int sts, uint uid, struct copy_vars *vars );
|
void (*cb)( int sts, uint uid, struct copy_vars *vars );
|
||||||
void *aux;
|
void *aux;
|
||||||
|
@ -421,7 +440,7 @@ msg_fetched( int sts, void *aux )
|
||||||
return;
|
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;
|
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;
|
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" );
|
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" );
|
debug( "synchronizing old entries\n" );
|
||||||
for (srec = svars->srecs; srec; srec = srec->next) {
|
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 {
|
} else {
|
||||||
// We have a source. The target may be in an unknown state.
|
// We have a source. The target may be in an unknown state.
|
||||||
if (svars->chan->ops[t] & OP_FLAGS) {
|
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))) {
|
if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) {
|
||||||
/* Don't propagate deletion resulting from expiration. */
|
/* Don't propagate deletion resulting from expiration. */
|
||||||
debug( " slave expiring\n" );
|
debug( " slave expiring\n" );
|
||||||
|
|
Loading…
Reference in New Issue
Block a user