Skip to content

Commit

Permalink
mboxlist.c: add 'U' field (user inboxid) to mbentry_t
Browse files Browse the repository at this point in the history
  • Loading branch information
ksmurchison committed Jun 21, 2024
1 parent e862ccc commit 5ea6581
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 33 deletions.
83 changes: 54 additions & 29 deletions imap/ctl_cyrusdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,17 @@ static void usage(void)
exit(-1);
}

struct fix_rock {
char *inboxname;
char *inboxid;
};

/* Callback for use by process_mboxlist */
static int fixmbox(const mbentry_t *mbentry,
void *rock __attribute__((unused)))
static int fixmbox(const mbentry_t *mbentry, void *rock)
{
struct fix_rock *frock = (struct fix_rock *) rock;
struct mailbox *mailbox = NULL;
mbentry_t *copy = NULL;
int r, r2;

/* if MBTYPE_RESERVED, unset it & call mboxlist_delete */
Expand Down Expand Up @@ -160,17 +167,12 @@ static int fixmbox(const mbentry_t *mbentry,
buf_free(&buf);
free(userid);
}
mbentry_t *copy = mboxlist_entry_copy(mbentry);
mbentry = copy = mboxlist_entry_copy(mbentry);
xzfree(copy->legacy_specialuse);
mboxlist_updatelock(copy, /*localonly*/1);
mboxlist_entry_free(&copy);
}

/* make sure every local mbentry has a uniqueid! */
if (!mbentry->uniqueid && mbentry_is_local_mailbox(mbentry)) {
struct mailbox *mailbox = NULL;
mbentry_t *copy = NULL;

r = mailbox_open_from_mbe(mbentry, &mailbox);
if (r) {
/* XXX what does it mean if there's an mbentry, but the mailbox
Expand All @@ -189,35 +191,55 @@ static int fixmbox(const mbentry_t *mbentry,
mbentry->name, mailbox->h.uniqueid);
}

copy = mboxlist_entry_copy(mbentry);
if (!copy) mbentry = copy = mboxlist_entry_copy(mbentry);
copy->uniqueid = xstrdup(mailbox->h.uniqueid);
xsyslog(LOG_INFO, "mbentry had no uniqueid, setting from header",
"mboxname=<%s> newuniqueid=<%s>",
copy->name, copy->uniqueid);

skip_uniqueid:
; /* hush "label at end of compound statement" warning */
}

if (mboxname_isusermailbox(mbentry->name, 1)) {
free(frock->inboxname);
free(frock->inboxid);
frock->inboxname = xstrdup(mbentry->name);
frock->inboxid = xstrdup(mbentry->uniqueid);
}
if (!mbentry->inboxid && frock->inboxname &&
mboxname_is_prefix(mbentry->name, frock->inboxname)) {
xsyslog(LOG_INFO, "mbentry had no inboxid, setting from inbox",
"mboxname=<%s> inboxname=<%s> inboxid=<%s>",
mbentry->name, frock->inboxname, frock->inboxid);
if (!copy) mbentry = copy = mboxlist_entry_copy(mbentry);
copy->inboxid = xstrdup(frock->inboxid);
}

if (copy) {
r = mboxlist_updatelock(copy, /*localonly*/1);
if (r) {
xsyslog(LOG_ERR, "failed to update mboxlist",
"mboxname=<%s> error=<%s>",
mbentry->name, error_message(r));
r2 = mailbox_abort(mailbox);
if (r2) {
xsyslog(LOG_ERR, "DBERROR: error aborting transaction",
"error=<%s>", cyrusdb_strerror(r2));
mboxlist_entry_free(&copy);

if (mailbox) {
if (r) {
xsyslog(LOG_ERR, "failed to update mboxlist",
"mboxname=<%s> error=<%s>",
mbentry->name, error_message(r));
r2 = mailbox_abort(mailbox);
if (r2) {
xsyslog(LOG_ERR, "DBERROR: error aborting transaction",
"error=<%s>", cyrusdb_strerror(r2));
}
}
}
else {
r2 = mailbox_commit(mailbox);
if (r2) {
xsyslog(LOG_ERR, "DBERROR: error committing transaction",
"error=<%s>", cyrusdb_strerror(r2));
else {
r2 = mailbox_commit(mailbox);
if (r2) {
xsyslog(LOG_ERR, "DBERROR: error committing transaction",
"error=<%s>", cyrusdb_strerror(r2));
}
}
mailbox_close(&mailbox);
}
mailbox_close(&mailbox);
mboxlist_entry_free(&copy);

skip_uniqueid:
; /* hush "label at end of compound statement" warning */
}

return 0;
Expand All @@ -229,7 +251,10 @@ static void process_mboxlist(int *upgraded)
mboxlist_upgrade(upgraded);

/* run fixmbox across all mboxlist entries */
mboxlist_allmbox(NULL, fixmbox, NULL, MBOXTREE_INTERMEDIATES);
struct fix_rock frock = { 0 };
mboxlist_allmbox(NULL, fixmbox, &frock, MBOXTREE_INTERMEDIATES);
free(frock.inboxname);
free(frock.inboxid);

/* enable or disable RACLs per config */
mboxlist_set_racls(config_getswitch(IMAPOPT_REVERSEACLS));
Expand Down
3 changes: 3 additions & 0 deletions imap/ctl_mboxlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ static int dump_cb(const mbentry_t *mbentry, void *rockp)
/* char *uniqueid; */
json_object_set_new(jobj, "uniqueid", json_string(mbentry->uniqueid));

/* char *inboxid; */
json_object_set_new(jobj, "inboxid", json_string(mbentry->inboxid));

/* char *legacy_specialuse; */
json_object_set_new(jobj, "legacy_specialuse",
json_string(mbentry->legacy_specialuse));
Expand Down
25 changes: 23 additions & 2 deletions imap/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -1134,6 +1134,11 @@ EXPORTED const char *mailbox_uniqueid(const struct mailbox *mailbox)
return mbentry->uniqueid ? mbentry->uniqueid : mailbox->h.uniqueid;
}

EXPORTED const char *mailbox_inboxid(const struct mailbox *mailbox)
{
return mailbox->mbentry->inboxid;
}

EXPORTED const char *mailbox_partition(const struct mailbox *mailbox)
{
return mailbox->mbentry->partition;
Expand Down Expand Up @@ -5861,10 +5866,10 @@ EXPORTED int mailbox_create(const char *name,
mailbox = create_listitem(lockname);

/* needs to be an exclusive namelock to create a mailbox */
char *userid = mboxname_to_userid(name);
mbname_t *mbname = mbname_from_intname(name);
const char *userid = mbname_userid(mbname);
int haslock = user_isnamespacelocked(userid);
assert(haslock == LOCK_EXCLUSIVE);
free(userid);

r = mboxname_lock(mailbox->lockname, &mailbox->namelock, LOCK_EXCLUSIVE);
if (r) {
Expand All @@ -5880,6 +5885,22 @@ EXPORTED int mailbox_create(const char *name,
mailbox->mbentry->mbtype = mbtype;
mailbox->mbentry->uniqueid = xstrdup(uniqueid);

if (userid) {
// add inboxid to mbentry
if (!strarray_size(mbname_boxes(mbname)))
mailbox->mbentry->inboxid = xstrdup(uniqueid);
else {
mbentry_t *usermbentry = NULL;
mbname_set_boxes(mbname, NULL);
mboxlist_lookup(mbname_intname(mbname), &usermbentry, NULL);
if (usermbentry) {
mailbox->mbentry->inboxid = xstrdup(usermbentry->uniqueid);
mboxlist_entry_free(&usermbentry);
}
}
}
mbname_free(&mbname);

// fill out the header too
mailbox->h.name = xstrdup(name);
mailbox->h.acl = xstrdup(acl);
Expand Down
1 change: 1 addition & 0 deletions imap/mailbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ extern int mailbox_delete(struct mailbox **mailboxptr);
/* reading details */
extern const char *mailbox_name(const struct mailbox *mailbox);
extern const char *mailbox_uniqueid(const struct mailbox *mailbox);
extern const char *mailbox_inboxid(const struct mailbox *mailbox);
extern const char *mailbox_partition(const struct mailbox *mailbox);
extern const char *mailbox_acl(const struct mailbox *mailbox);
extern const char *mailbox_quotaroot(const struct mailbox *mailbox);
Expand Down
19 changes: 18 additions & 1 deletion imap/mboxlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ EXPORTED mbentry_t *mboxlist_entry_copy(const mbentry_t *src)
copy->server = xstrdupnull(src->server);
copy->acl = xstrdupnull(src->acl);
copy->uniqueid = xstrdupnull(src->uniqueid);
copy->inboxid = xstrdupnull(src->inboxid);

copy->legacy_specialuse = xstrdupnull(src->legacy_specialuse);

Expand Down Expand Up @@ -187,6 +188,7 @@ EXPORTED void mboxlist_entry_free(mbentry_t **mbentryptr)
free(mbentry->server);
free(mbentry->acl);
free(mbentry->uniqueid);
free(mbentry->inboxid);

free(mbentry->legacy_specialuse);

Expand Down Expand Up @@ -273,6 +275,9 @@ static struct dlist *mboxlist_entry_dlist(const char *dbname,
else if (mbentry->uniqueid)
dlist_setatom(dl, "I", mbentry->uniqueid);

if (mbentry->inboxid)
dlist_setatom(dl, "U", mbentry->inboxid);

if (mbentry->partition)
dlist_setatom(dl, "P", mbentry->partition);

Expand Down Expand Up @@ -618,6 +623,9 @@ static int parseentry_cb(int type, struct dlistsax_data *d)
else if (!strcmp(key, "I")) {
rock->mbentry->uniqueid = xstrdupnull(d->data);
}
else if (!strcmp(key, "U")) {
rock->mbentry->inboxid = xstrdupnull(d->data);
}
else if (!strcmp(key, "M")) {
rock->mbentry->mtime = atoi(d->data);
}
Expand Down Expand Up @@ -652,6 +660,7 @@ static int parseentry_cb(int type, struct dlistsax_data *d)
* F: _f_oldermodseq
* H: name_h_istory
* I: unique_i_d
* U: _u_serinboxid
* M: _m_time
* N: _n_ame
* P: _p_artition
Expand Down Expand Up @@ -1869,6 +1878,7 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
int isremote = mbtype & MBTYPE_REMOTE;
mbentry_t *usermbentry = NULL, *newmbentry = NULL;
int silent = 0;
int isinbox;

init_internal();

Expand All @@ -1878,6 +1888,8 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,

assert_namespacelocked(mboxname);

isinbox = mboxname_isusermailbox(mboxname, 1);

if ((flags & MBOXLIST_CREATE_SYNC)) {
silent = 1;
}
Expand Down Expand Up @@ -1937,9 +1949,11 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
newmbentry->mbtype = mbtype;
newmbentry->partition = xstrdupnull(newpartition);
newmbentry->uniqueid = xstrdup(uniqueid ? uniqueid : makeuuid());
if (isinbox) newmbentry->inboxid = xstrdup(newmbentry->uniqueid);
else if (usermbentry) newmbentry->inboxid = xstrdup(usermbentry->uniqueid);

if (!(flags & MBOXLIST_CREATE_DBONLY) && !isremote) {
if (mboxname_isusermailbox(mboxname, 1)) {
if (isinbox) {
/* Create initial mbentry for new users --
the uniqueid in the record is required to open
user metadata files (conversations, counters) */
Expand Down Expand Up @@ -2769,6 +2783,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry,
newmbentry->acl = xstrdupnull(mailbox_acl(oldmailbox));
newmbentry->uidvalidity = oldmailbox->i.uidvalidity;
newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(oldmailbox));
newmbentry->inboxid = xstrdupnull(mailbox_inboxid(oldmailbox));
newmbentry->createdmodseq = oldmailbox->i.createdmodseq;
newmbentry->foldermodseq = silent ? mailbox_foldermodseq(oldmailbox)
: mboxname_nextmodseq(newname, mailbox_foldermodseq(oldmailbox),
Expand Down Expand Up @@ -2833,6 +2848,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry,
newmbentry->acl = xstrdupnull(mailbox_acl(newmailbox));
newmbentry->uidvalidity = newmailbox->i.uidvalidity;
newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(newmailbox));
newmbentry->inboxid = xstrdupnull(mailbox_inboxid(newmailbox));
newmbentry->createdmodseq = newmailbox->i.createdmodseq;
newmbentry->foldermodseq = newmailbox->i.highestmodseq;
}
Expand All @@ -2845,6 +2861,7 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry,
newmbentry->acl = xstrdupnull(mailbox_acl(oldmailbox));
newmbentry->uidvalidity = oldmailbox->i.uidvalidity;
newmbentry->uniqueid = xstrdupnull(mailbox_uniqueid(oldmailbox));
newmbentry->inboxid = xstrdupnull(mailbox_inboxid(oldmailbox));
newmbentry->createdmodseq = oldmailbox->i.createdmodseq;
newmbentry->foldermodseq = oldmailbox->i.highestmodseq;

Expand Down
3 changes: 2 additions & 1 deletion imap/mboxlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,15 @@ struct mboxlist_entry {
char *acl;
/* extra fields */
char *uniqueid;
char *inboxid;
/* legacy upgrade support */
char *legacy_specialuse;
/* replication support */
ptrarray_t name_history;
};

#define MBENTRY_INITIALIZER { NULL, NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, \
NULL, NULL, PTRARRAY_INITIALIZER }
NULL, NULL, NULL, PTRARRAY_INITIALIZER }

typedef struct mboxlist_entry mbentry_t;

Expand Down

0 comments on commit 5ea6581

Please sign in to comment.