From: Bron Gondwana <br...@launde.home.brong.net> Rewrite the mailboxopt annotations to be data driven, and use the same struct to process ALL annotations on the mailbox options field during a sync run. Fixes duplicatedeliver and sharedseen synchronisation, and is future-proof. --- imap/annotate.c | 47 ++++++++++++++++++++++++++--------------------- imap/annotate.h | 8 ++++++++ imap/mailbox.h | 3 ++- imap/sync_client.c | 13 +++++++------ 4 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/imap/annotate.c b/imap/annotate.c index 45db495..1484079 100644 --- a/imap/annotate.c +++ b/imap/annotate.c @@ -422,6 +422,17 @@ struct mailbox_annotation_rock char *server, *partition, *acl, *path, *mpath; }; +const struct annotate_info_t annotate_mailbox_flags[] = +{ + { "/vendor/cmu/cyrus-imapd/duplicatedeliver", + OPT_IMAP_DUPDELIVER }, + { "/vendor/cmu/cyrus-imapd/sharedseen", + OPT_IMAP_SHAREDSEEN }, + { "/vendor/cmu/cyrus-imapd/condstore", + OPT_IMAP_CONDSTORE }, + { NULL, 0 } +}; + /* To free values in the mailbox_annotation_rock as needed */ static void cleanup_mbrock(struct mailbox_annotation_rock *mbrock __attribute__((unused))) { @@ -878,7 +889,7 @@ static void annotation_get_mailboxopt(const char *int_mboxname, void *rock __attribute__((unused))) { struct mailbox mailbox; - int flag, r = 0; + int flag = 0, r = 0, i; char value[40]; struct annotation_data attrib; @@ -891,16 +902,14 @@ static void annotation_get_mailboxopt(const char *int_mboxname, /* Make sure its a local mailbox */ if (mbrock->server) return; - /* Check entry */ - if (!strcmp(entry, "/vendor/cmu/cyrus-imapd/condstore")) { - flag = OPT_IMAP_CONDSTORE; - } else if (!strcmp(entry, "/vendor/cmu/cyrus-imapd/sharedseen")) { - flag = OPT_IMAP_SHAREDSEEN; - } else if (!strcmp(entry, "/vendor/cmu/cyrus-imapd/duplicatedeliver")) { - flag = OPT_IMAP_DUPDELIVER; - } else { - return; + /* check that this is a mailboxopt annotation */ + for (i = 0; annotate_mailbox_flags[i].name; i++) { + if (!strcmp(entry, annotate_mailbox_flags[i].name)) { + flag = annotate_mailbox_flags[i].flag; + break; + } } + if (!flag) return; /* Check ACL */ if(!fdata->isadmin && @@ -1717,20 +1726,16 @@ static int annotation_set_mailboxopt(const char *int_mboxname, void *rock __attribute__((unused))) { struct mailbox mailbox; - int flag, r = 0; + int flag = 0, r = 0, i; /* Check entry */ - if (!strcmp(entry->entry->name, "/vendor/cmu/cyrus-imapd/condstore")) { - flag = OPT_IMAP_CONDSTORE; - } else if (!strcmp(entry->entry->name, - "/vendor/cmu/cyrus-imapd/sharedseen")) { - flag = OPT_IMAP_SHAREDSEEN; - } else if (!strcmp(entry->entry->name, - "/vendor/cmu/cyrus-imapd/duplicatedeliver")) { - flag = OPT_IMAP_DUPDELIVER; - } else { - return IMAP_PERMISSION_DENIED; + for (i = 0; annotate_mailbox_flags[i].name; i++) { + if (!strcmp(entry->entry->name, annotate_mailbox_flags[i].name)) { + flag = annotate_mailbox_flags[i].flag; + break; + } } + if (!flag) return IMAP_PERMISSION_DENIED; /* Check ACL */ if(!sdata->isadmin && diff --git a/imap/annotate.h b/imap/annotate.h index 4482580..5f8d7dc 100644 --- a/imap/annotate.h +++ b/imap/annotate.h @@ -119,6 +119,14 @@ struct annotation_data { const char *contenttype; }; +struct annotate_info_t +{ + const char *name; + int flag; +}; + +extern const struct annotate_info_t annotate_mailbox_flags[]; + /* lookup a single annotation and return result */ int annotatemore_lookup(const char *mboxname, const char *entry, const char *userid, struct annotation_data *attrib); diff --git a/imap/mailbox.h b/imap/mailbox.h index 066a435..0c6c887 100644 --- a/imap/mailbox.h +++ b/imap/mailbox.h @@ -257,11 +257,12 @@ struct index_record { #define FLAG_DRAFT (1<<3) #define OPT_POP3_NEW_UIDL (1<<0) /* added for Outlook stupidity */ +/* these three are annotations, if you add more, update annotate.c + * struct annotate_mailbox_flags */ #define OPT_IMAP_CONDSTORE (1<<1) /* added for CONDSTORE extension */ #define OPT_IMAP_SHAREDSEEN (1<<2) /* added for shared \Seen flag */ #define OPT_IMAP_DUPDELIVER (1<<3) /* added to allow duplicate delivery */ - struct mailbox_header_cache { const char *name; /* Name of header */ bit32 min_cache_version; /* Cache version it appeared in */ diff --git a/imap/sync_client.c b/imap/sync_client.c index da6e271..d08f5c4 100644 --- a/imap/sync_client.c +++ b/imap/sync_client.c @@ -1828,7 +1828,7 @@ int do_folders(struct sync_folder_list *client_list, int doing_user) { struct mailbox m; - int r = 0, mailbox_open = 0; + int r = 0, mailbox_open = 0, i; struct sync_rename_list *rename_list = sync_rename_list_create(); struct sync_folder *folder, *folder2; @@ -1978,13 +1978,14 @@ int do_folders(struct sync_folder_list *client_list, if (!r && (m.uidvalidity != folder2->uidvalidity)) r = folder_setuidvalidity(folder->name, m.uidvalidity); - if (!r && - (folder2->options ^ m.options) & OPT_IMAP_CONDSTORE) { - r = folder_setannotation(m.name, - "/vendor/cmu/cyrus-imapd/condstore", + for (i = 0; !r && annotate_mailbox_flags[i].name; i++) { + if ((folder2->options ^ m.options) & annotate_mailbox_flags[i].flag) { + r = folder_setannotation(m.name, + annotate_mailbox_flags[i].name, "", - (m.options & OPT_IMAP_CONDSTORE) ? + (m.options & annotate_mailbox_flags[i].flag) ? "true" : "false"); + } } if (!r && m.quota.root && !strcmp(m.name, m.quota.root)) -- 1.5.6.3