static int mailbox_update_carddav(struct mailbox *mailbox,
                                  const struct index_record *new)
{
    struct carddav_db *carddavdb = NULL;
    struct param *param;
    struct body *body = NULL;
    struct carddav_data *cdata = NULL;
    const char *resource = NULL;
    int r = 0;

    r = mailbox_cacherecord(mailbox, new);
    if (r) goto done;

    /* Get resource URL from filename param in Content-Disposition header */
    message_read_bodystructure(new, &body);
    for (param = body->disposition_params; param; param = param->next) {
        if (!strcmp(param->attribute, "FILENAME")) {
            resource = param->value;
        }
    }

    assert(resource);

    carddavdb = mailbox_open_carddav(mailbox);

    /* find existing record for this resource */
    const mbentry_t mbentry = { .name = (char *)mailbox_name(mailbox),
                                .uniqueid = (char *)mailbox_uniqueid(mailbox) };

    carddav_lookup_resource(carddavdb, &mbentry, resource, &cdata, /*tombstones*/1);

    /* does it still come from this UID? */
    if (cdata->dav.imap_uid > new->uid) goto done;

    if (new->internal_flags & FLAG_INTERNAL_UNLINKED) {
        /* is there an existing record? */
        if (!cdata->dav.imap_uid) goto done;

        /* delete entry */
        r = carddav_delete(carddavdb, cdata->dav.rowid);
    }
    else if (cdata->dav.imap_uid == new->uid) {
        /* just a flag change on an existing record */
        int ispinned = (new->system_flags & FLAG_FLAGGED) ? 1 : 0;

        cdata->dav.modseq = new->modseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;
        r = carddav_update(carddavdb, cdata, ispinned);
    }
    else {
        /* Load message containing the resource and parse vcard data */
        struct vparse_card *vcard = record_to_vcard(mailbox, new);
        int ispinned = (new->system_flags & FLAG_FLAGGED) ? 1 : 0;

        if (!vcard || !vcard->objects) {
            syslog(LOG_ERR, "record_to_vcard failed for record %u:%s",
                   cdata->dav.imap_uid, mailbox_name(mailbox));
            r = IMAP_MAILBOX_BADFORMAT; // XXX better error?
            vparse_free_card(vcard);
            goto done;
        }

        /* Create mapping entry from resource name to UID */
        cdata->dav.imap_uid = new->uid;
        cdata->dav.modseq = new->modseq;
        cdata->dav.createdmodseq = new->createdmodseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;

        if (!cdata->dav.creationdate)
            cdata->dav.creationdate = new->internaldate;

        r = carddav_writecard(carddavdb, cdata, vcard->objects, ispinned);

        vparse_free_card(vcard);
    }

done:
    message_free_body(body);
    free(body);

    return r;
}
static int mailbox_update_carddav(struct mailbox *mailbox,
                                  const struct index_record *new)
{
    struct carddav_db *carddavdb = NULL;
    struct param *param;
    struct body *body = NULL;
    struct carddav_data *cdata = NULL;
    const char *resource = NULL;
    int r = 0;

    r = mailbox_cacherecord(mailbox, new);
    if (r) goto done;

     
    message_read_bodystructure(new, &body);
    for (param = body->disposition_params; param; param = param->next) {
        if (!strcmp(param->attribute, "FILENAME")) {
            resource = param->value;
        }
    }

    assert(resource);

    carddavdb = mailbox_open_carddav(mailbox);

     
    const mbentry_t mbentry = { .name = (char *)mailbox_name(mailbox),
                                .uniqueid = (char *)mailbox_uniqueid(mailbox) };

    carddav_lookup_resource(carddavdb, &mbentry, resource, &cdata,  1);

     
    if (cdata->dav.imap_uid > new->uid) goto done;

    if (new->internal_flags & FLAG_INTERNAL_UNLINKED) {
         
        if (!cdata->dav.imap_uid) goto done;

         
        r = carddav_delete(carddavdb, cdata->dav.rowid);
    }
    else if (cdata->dav.imap_uid == new->uid) {
         
        int ispinned = (new->system_flags & FLAG_FLAGGED) ? 1 : 0;

        cdata->dav.modseq = new->modseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;
        r = carddav_update(carddavdb, cdata, ispinned);
    }
    else {
         
        struct vparse_card *vcard = record_to_vcard(mailbox, new);
        int ispinned = (new->system_flags & FLAG_FLAGGED) ? 1 : 0;

        if (!vcard || !vcard->objects) {
            syslog(LOG_ERR, "record_to_vcard failed for record %u:%s",
                   cdata->dav.imap_uid, mailbox_name(mailbox));
            r = IMAP_MAILBOX_BADFORMAT;  
            vparse_free_card(vcard);
            goto done;
        }

         
        cdata->dav.imap_uid = new->uid;
        cdata->dav.modseq = new->modseq;
        cdata->dav.createdmodseq = new->createdmodseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;

        if (!cdata->dav.creationdate)
            cdata->dav.creationdate = new->internaldate;

        r = carddav_writecard(carddavdb, cdata, vcard->objects, ispinned);

        vparse_free_card(vcard);
    }

done:
    message_free_body(body);
    free(body);

    return r;
}