static int mailbox_update_caldav(struct mailbox *mailbox,
                                 const struct index_record *new)
{
    struct caldav_db *caldavdb = NULL;
    struct param *param;
    struct body *body = NULL;
    struct caldav_data *cdata = NULL;
    const char *resource = NULL;
    const char *sched_tag = NULL;
    unsigned tzbyref = 0, shared = 0;
    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;
        }
        else if (!strcmp(param->attribute, "SCHEDULE-TAG")) {
            sched_tag = param->value;
        }
        else if (!strcmp(param->attribute, "TZ-BY-REF")) {
            tzbyref = !strcasecmp(param->value, "TRUE");
        }
        else if (!strcmp(param->attribute, "PER-USER-DATA")) {
            shared = !strcasecmp(param->value, "TRUE");
        }
    }

    caldavdb = mailbox_open_caldav(mailbox);

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

    caldav_lookup_resource(caldavdb, &mbentry, resource, &cdata, /*tombstones*/1);

    /* has this record already been replaced?  Don't write anything */
    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;

        /* remove associated alarms */
        caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);

        /* delete entry */
        r = caldav_delete(caldavdb, cdata->dav.rowid);
    }
    else if (cdata->dav.imap_uid == new->uid) {
        if (new->internal_flags & FLAG_INTERNAL_EXPUNGED) {
            /* remove associated alarms */
            caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);
        }
        else if (!new->silentupdate) {
            /* make sure record is up to date - see add below for description of
             * why we don't touch silent records */
            caldav_alarm_touch_record(mailbox, new, 0);
        }

        /* just a flags update to an existing record */
        cdata->dav.modseq = new->modseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;
        r = caldav_write(caldavdb, cdata);
    }
    else {
        /* Load message containing the resource and parse ical data */
        icalcomponent *ical = record_to_ical(mailbox, new, NULL);

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

        /* remove old ones */
        if (cdata->dav.imap_uid) {
            r = caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);
            if (r) goto alarmdone;
        }

        cdata->dav.creationdate = new->internaldate;
        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;
        cdata->sched_tag = sched_tag;
        cdata->comp_flags.tzbyref = tzbyref;
        cdata->comp_flags.shared = shared;

        /* add new ones unless this record is expunged */
        /* we need to skip silent records (replication)
         * because the lastalarm annotation won't be set yet -
         * instead, we have an explicit sync from the annotation
         * which is done after the annotations are written in sync_support.c */
        if (cdata->dav.alive && !new->silentupdate) {
            r = caldav_alarm_add_record(mailbox, new, ical);
            if (r) goto alarmdone;
        }

        r = caldav_writeical(caldavdb, cdata, ical);

     alarmdone:
        icalcomponent_free(ical);
    }

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

    return r;
}
static int mailbox_update_caldav(struct mailbox *mailbox,
                                 const struct index_record *new)
{
    struct caldav_db *caldavdb = NULL;
    struct param *param;
    struct body *body = NULL;
    struct caldav_data *cdata = NULL;
    const char *resource = NULL;
    const char *sched_tag = NULL;
    unsigned tzbyref = 0, shared = 0;
    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;
        }
        else if (!strcmp(param->attribute, "SCHEDULE-TAG")) {
            sched_tag = param->value;
        }
        else if (!strcmp(param->attribute, "TZ-BY-REF")) {
            tzbyref = !strcasecmp(param->value, "TRUE");
        }
        else if (!strcmp(param->attribute, "PER-USER-DATA")) {
            shared = !strcasecmp(param->value, "TRUE");
        }
    }

    caldavdb = mailbox_open_caldav(mailbox);

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

    caldav_lookup_resource(caldavdb, &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;

         
        caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);

         
        r = caldav_delete(caldavdb, cdata->dav.rowid);
    }
    else if (cdata->dav.imap_uid == new->uid) {
        if (new->internal_flags & FLAG_INTERNAL_EXPUNGED) {
             
            caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);
        }
        else if (!new->silentupdate) {
             
            caldav_alarm_touch_record(mailbox, new, 0);
        }

         
        cdata->dav.modseq = new->modseq;
        cdata->dav.alive = (new->internal_flags & FLAG_INTERNAL_EXPUNGED) ? 0 : 1;
        r = caldav_write(caldavdb, cdata);
    }
    else {
         
        icalcomponent *ical = record_to_ical(mailbox, new, NULL);

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

         
        if (cdata->dav.imap_uid) {
            r = caldav_alarm_delete_record(cdata->dav.mailbox, cdata->dav.imap_uid);
            if (r) goto alarmdone;
        }

        cdata->dav.creationdate = new->internaldate;
        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;
        cdata->sched_tag = sched_tag;
        cdata->comp_flags.tzbyref = tzbyref;
        cdata->comp_flags.shared = shared;

         
         
        if (cdata->dav.alive && !new->silentupdate) {
            r = caldav_alarm_add_record(mailbox, new, ical);
            if (r) goto alarmdone;
        }

        r = caldav_writeical(caldavdb, cdata, ical);

     alarmdone:
        icalcomponent_free(ical);
    }

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

    return r;
}