static int parseentry_cb(int type, struct dlistsax_data *d)
{
    struct parseentry_rock *rock = (struct parseentry_rock *)d->rock;

    const char *key = buf_cstring(&d->kbuf);

    switch(type) {
    case DLISTSAX_KVLISTSTART:
        if (!strcmp(key, "A")) {
            rock->doingacl = 1;
        }
        break;
    case DLISTSAX_KVLISTEND:
        if (rock->doingacl) {
            xzfree(rock->h->acl);
            rock->h->acl = buf_release(&rock->aclbuf);
            rock->doingacl = 0;
        }
        break;
    case DLISTSAX_LISTSTART:
        if (!strcmp(key, "U")) {
            rock->doingflags = 1;
            rock->nflags = 0;
        }
        break;
    case DLISTSAX_LISTEND:
        if (rock->doingflags) {
            rock->doingflags = 0;

            /* zero out the rest */
            while (rock->nflags < MAX_USER_FLAGS) {
                xzfree(rock->h->flagname[rock->nflags++]);
            }
        }
        break;
    case DLISTSAX_STRING:
        if (rock->doingacl) {
            buf_append(&rock->aclbuf, &d->kbuf);
            buf_putc(&rock->aclbuf, '\t');
            buf_appendcstr(&rock->aclbuf, d->data);
            buf_putc(&rock->aclbuf, '\t');
        }
        else if (rock->doingflags) {
            xzfree(rock->h->flagname[rock->nflags]);
            rock->h->flagname[rock->nflags++] = xstrdupnull(d->data);
        }
        else {
            if (!strcmp(key, "I")) {
                xzfree(rock->h->uniqueid);
                rock->h->uniqueid = xstrdupnull(d->data);
            }
            else if (!strcmp(key, "N")) {
                xzfree(rock->h->name);
                rock->h->name = xstrdupnull(d->data);
            }
            else if (!strcmp(key, "T")) {
                rock->h->mbtype = mboxlist_string_to_mbtype(d->data);
            }
            else if (!strcmp(key, "Q")) {
                xzfree(rock->h->quotaroot);
                rock->h->quotaroot = xstrdupnull(d->data);
            }
        }
    }

    return 0;
}
static int parseentry_cb(int type, struct dlistsax_data *d)
{
    struct parseentry_rock *rock = (struct parseentry_rock *)d->rock;

    const char *key = buf_cstring(&d->kbuf);

    switch(type) {
    case DLISTSAX_KVLISTSTART:
        if (!strcmp(key, "A")) {
            rock->doingacl = 1;
        }
        break;
    case DLISTSAX_KVLISTEND:
        if (rock->doingacl) {
            xzfree(rock->h->acl);
            rock->h->acl = buf_release(&rock->aclbuf);
            rock->doingacl = 0;
        }
        break;
    case DLISTSAX_LISTSTART:
        if (!strcmp(key, "U")) {
            rock->doingflags = 1;
            rock->nflags = 0;
        }
        break;
    case DLISTSAX_LISTEND:
        if (rock->doingflags) {
            rock->doingflags = 0;

             
            while (rock->nflags < MAX_USER_FLAGS) {
                xzfree(rock->h->flagname[rock->nflags++]);
            }
        }
        break;
    case DLISTSAX_STRING:
        if (rock->doingacl) {
            buf_append(&rock->aclbuf, &d->kbuf);
            buf_putc(&rock->aclbuf, '\t');
            buf_appendcstr(&rock->aclbuf, d->data);
            buf_putc(&rock->aclbuf, '\t');
        }
        else if (rock->doingflags) {
            xzfree(rock->h->flagname[rock->nflags]);
            rock->h->flagname[rock->nflags++] = xstrdupnull(d->data);
        }
        else {
            if (!strcmp(key, "I")) {
                xzfree(rock->h->uniqueid);
                rock->h->uniqueid = xstrdupnull(d->data);
            }
            else if (!strcmp(key, "N")) {
                xzfree(rock->h->name);
                rock->h->name = xstrdupnull(d->data);
            }
            else if (!strcmp(key, "T")) {
                rock->h->mbtype = mboxlist_string_to_mbtype(d->data);
            }
            else if (!strcmp(key, "Q")) {
                xzfree(rock->h->quotaroot);
                rock->h->quotaroot = xstrdupnull(d->data);
            }
        }
    }

    return 0;
}