Skip to content

Commit

Permalink
sync_support: replica USERGROUPs with inboxes on RACLMODSEQ bump
Browse files Browse the repository at this point in the history
  • Loading branch information
brong committed May 8, 2024
1 parent 677508d commit 1d713fb
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 12 deletions.
6 changes: 3 additions & 3 deletions backup/restore.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ static struct sync_folder_list *restore_make_reserve_folder_list(
/* we only care about mboxname here */
sync_folder_list_add(folder_list, NULL, iter->mboxname,
0, NULL, NULL, 0, 0, 0, 0, synccrcs,
0, 0, 0, 0, NULL, 0, 0, 0, 0);
0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0);
}

backup_mailbox_list_empty(mailboxes);
Expand Down Expand Up @@ -751,7 +751,7 @@ static int restore_add_mailbox(const struct backup_mailbox *mailbox,
const struct synccrcs synccrcs = {0, 0};
sync_folder_list_add(reserve_folder_list, NULL, clone->mboxname,
0, NULL, NULL, 0, 0, 0, 0, synccrcs,
0, 0, 0, 0, NULL, 0, 0, 0, 0);
0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0);
}

/* populate mailbox list */
Expand Down Expand Up @@ -795,7 +795,7 @@ static int restore_add_message(const struct backup_message *message,
const struct synccrcs synccrcs = {0, 0};
sync_folder_list_add(reserve_folder_list, NULL, mailbox->mboxname,
0, NULL, NULL, 0, 0, 0, 0, synccrcs,
0, 0, 0, 0, NULL, 0, 0, 0, 0);
0, 0, 0, 0, NULL, 0, 0, 0, NULL, 0);

/* add to mailbox list */
my_mailbox_list_add(mailbox_list, mailbox);
Expand Down
1 change: 1 addition & 0 deletions imap/imapd.c
Original file line number Diff line number Diff line change
Expand Up @@ -12711,6 +12711,7 @@ static int sync_mailbox(struct xfer_header *xfer,
xconvmodseq,
raclmodseq,
mailbox_foldermodseq(mailbox),
/* groups */ NULL,
/* ispartial */0);
annots = NULL; /* list took ownership */

Expand Down
60 changes: 51 additions & 9 deletions imap/sync_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,7 @@ struct sync_folder *sync_folder_list_add(struct sync_folder_list *l,
modseq_t xconvmodseq,
modseq_t raclmodseq,
modseq_t foldermodseq,
const char *groups,
int ispartial)
{
struct sync_folder *result = xzmalloc(sizeof(struct sync_folder));
Expand Down Expand Up @@ -637,6 +638,7 @@ struct sync_folder *sync_folder_list_add(struct sync_folder_list *l,
result->xconvmodseq = xconvmodseq;
result->raclmodseq = raclmodseq;
result->foldermodseq = foldermodseq;
result->groups = xstrdupnull(groups);
result->ispartial = ispartial;

result->mark = 0;
Expand Down Expand Up @@ -1966,10 +1968,6 @@ static int sync_prepare_dlists(struct mailbox *mailbox,
dlist_setdate(kl, "LAST_APPENDDATE", 0);
dlist_setdate(kl, "POP3_LAST_LOGIN", remote ? remote->pop3_last_login : 0);
dlist_setdate(kl, "POP3_SHOW_AFTER", remote ? remote->pop3_show_after : 0);
if (remote && remote->xconvmodseq)
dlist_setnum64(kl, "XCONVMODSEQ", remote->xconvmodseq);
if (remote && remote->raclmodseq)
dlist_setnum64(kl, "RACLMODSEQ", remote->raclmodseq);
}
else {
struct synccrcs synccrcs = mailbox_synccrcs(mailbox, /*force*/0);
Expand All @@ -1988,8 +1986,20 @@ static int sync_prepare_dlists(struct mailbox *mailbox,
dlist_setnum64(kl, "XCONVMODSEQ", xconvmodseq);
}
modseq_t raclmodseq = mboxname_readraclmodseq(mailbox_name(mailbox));
if (raclmodseq)
if (raclmodseq && (!remote || remote->raclmodseq != raclmodseq)) {
// only send if different
dlist_setnum64(kl, "RACLMODSEQ", raclmodseq);
char *userid = mboxname_to_userid(mailbox_name(mailbox));
strarray_t groups = STRARRAY_INITIALIZER;
int r = mboxlist_lookup_usergroups(userid, &groups);
if (!r && strarray_size(&groups)) {
char *groupstxt = strarray_join(&groups, "\t");
dlist_setatom(kl, "USERGROUPS", groupstxt);
free(groupstxt);
}
strarray_fini(&groups);
free(userid);
}
}
dlist_setnum32(kl, "UIDVALIDITY", mailbox->i.uidvalidity);
dlist_setatom(kl, "PARTITION", topart);
Expand Down Expand Up @@ -2714,6 +2724,7 @@ int sync_apply_mailbox(struct dlist *kin,
modseq_t xconvmodseq = 0;
modseq_t raclmodseq = 0;
modseq_t createdmodseq = 0;
const char *groups = NULL;

/* previous state markers */
modseq_t since_modseq = 0;
Expand Down Expand Up @@ -2795,6 +2806,7 @@ int sync_apply_mailbox(struct dlist *kin,
dlist_getnum64(kin, "XCONVMODSEQ", &xconvmodseq);
dlist_getnum64(kin, "RACLMODSEQ", &raclmodseq);
dlist_getnum64(kin, "FOLDERMODSEQ", &foldermodseq);
dlist_getatom(kin, "USERGROUPS", &groups);

/* Get the CRCs */
dlist_getnum32(kin, "SYNC_CRC", &synccrcs.basic);
Expand Down Expand Up @@ -3044,6 +3056,32 @@ int sync_apply_mailbox(struct dlist *kin,
}
}

if (groups) {
strarray_t mygroups = STRARRAY_INITIALIZER;
char *userid = mboxname_to_userid(mboxname);
r = mboxlist_lookup_usergroups(userid, &mygroups);
if (r) goto done;
strarray_t *usergroups = strarray_split(groups, "\t", 0);
int i;
// add any new
for (i = 0; i < strarray_size(usergroups); i++) {
const char *group = strarray_nth(usergroups, i);
if (strarray_find(&mygroups, group, 0) >= 0) continue;
r = mboxlist_set_usergroup(userid, group, /*add*/1, /*silent*/1);
if (r) goto done;
}
// remove any old
for (i = 0; i < strarray_size(&mygroups); i++) {
const char *group = strarray_nth(&mygroups, i);
if (strarray_find(usergroups, group, 0) >= 0) continue;
r = mboxlist_set_usergroup(userid, group, /*add*/0, /*silent*/1);
if (r) goto done;
}
strarray_free(usergroups);
free(userid);
strarray_fini(&mygroups);
}

r = sync_mailbox_compare_update(mailbox, kr, 0, part_list);
if (r) goto done;

Expand Down Expand Up @@ -3107,7 +3145,7 @@ int sync_apply_mailbox(struct dlist *kin,
mailbox->i.uidvalidity = mboxname_setuidvalidity(mailbox_name(mailbox), uidvalidity);
}

if (mailbox_has_conversations(mailbox)) {
if (mailbox_has_conversations(mailbox) && xconvmodseq) {
r = mailbox_update_xconvmodseq(mailbox, xconvmodseq, opt_force);
}

Expand Down Expand Up @@ -4644,7 +4682,7 @@ static int find_reserve_all(struct sync_name_list *mboxname_list,
0, 0,
0, 0,
NULL, 0,
0, mbentry->foldermodseq, 0);
0, mbentry->foldermodseq, NULL, 0);
mboxlist_entry_free(&mbentry);
continue;
}
Expand Down Expand Up @@ -4688,6 +4726,8 @@ static int find_reserve_all(struct sync_name_list *mboxname_list,
modseq_t tomodseq = mailbox->i.highestmodseq;
int ispartial = 0;

char *groups = NULL;

if (batchsize && touid - fromuid > batchsize) {
/* see if we actually need to calculate an intermediate state */
modseq_t frommodseq = rfolder ? rfolder->highestmodseq : 0;
Expand All @@ -4709,7 +4749,7 @@ static int find_reserve_all(struct sync_name_list *mboxname_list,
mailbox->i.recentuid, mailbox->i.recenttime,
mailbox->i.pop3_last_login,
mailbox->i.pop3_show_after, NULL, xconvmodseq,
raclmodseq, mailbox_foldermodseq(mailbox), ispartial);
raclmodseq, mailbox_foldermodseq(mailbox), groups, ispartial);


part_list = sync_reserve_partlist(reserve_list, topart ? topart : mailbox_partition(mailbox));
Expand Down Expand Up @@ -4994,6 +5034,7 @@ static int sync_kl_parse(struct dlist *kin,
modseq_t xconvmodseq = 0;
modseq_t raclmodseq = 0;
modseq_t foldermodseq = 0;
const char *groups = NULL;

if (!folder_list) return IMAP_PROTOCOL_BAD_PARAMETERS;
if (!dlist_getatom(kl, "UNIQUEID", &uniqueid)) return IMAP_PROTOCOL_BAD_PARAMETERS;
Expand All @@ -5015,6 +5056,7 @@ static int sync_kl_parse(struct dlist *kin,
dlist_getnum64(kl, "XCONVMODSEQ", &xconvmodseq);
dlist_getnum64(kl, "RACLMODSEQ", &raclmodseq);
dlist_getnum64(kl, "FOLDERMODSEQ", &foldermodseq);
dlist_getatom(kl, "USERGROUPS", &groups);

if (dlist_getlist(kl, "ANNOTATIONS", &al))
decode_annotations(al, &annots, NULL, NULL);
Expand All @@ -5029,7 +5071,7 @@ static int sync_kl_parse(struct dlist *kin,
pop3_last_login,
pop3_show_after, annots,
xconvmodseq, raclmodseq,
foldermodseq, /*ispartial*/0);
foldermodseq, groups, /*ispartial*/0);
}

else {
Expand Down
2 changes: 2 additions & 0 deletions imap/sync_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct sync_folder {
modseq_t xconvmodseq;
modseq_t raclmodseq;
modseq_t foldermodseq;
char *groups;
int ispartial;
struct quota quota;
int mark;
Expand Down Expand Up @@ -179,6 +180,7 @@ struct sync_folder *sync_folder_list_add(struct sync_folder_list *l,
modseq_t xconvmodseq,
modseq_t raclmodseq,
modseq_t foldermodseq,
const char *groups,
int ispartial);

struct sync_folder *sync_folder_lookup(struct sync_folder_list *l,
Expand Down

0 comments on commit 1d713fb

Please sign in to comment.