static const char *deliver_merge_reply(icalcomponent *ical,
				       icalcomponent *reply)
{
    struct hash_table comp_table;
    icalcomponent *comp, *itip;
    icalcomponent_kind kind;
    icalproperty *prop, *att;
    icalparameter *param;
    icalparameter_partstat partstat = ICAL_PARTSTAT_NONE;
    icalparameter_rsvp rsvp = ICAL_RSVP_NONE;
    const char *recurid, *attendee = NULL, *req_stat = SCHEDSTAT_SUCCESS;
    icalproperty_kind recip_kind;
    const char *(*get_recipient)(const icalproperty *);

    /* Add each component of old object to hash table for comparison */
    construct_hash_table(&comp_table, 10, 1);
    comp = icalcomponent_get_first_real_component(ical);
    kind = icalcomponent_isa(comp);
    do {
	prop =
	    icalcomponent_get_first_property(comp, ICAL_RECURRENCEID_PROPERTY);
	if (prop) recurid = icalproperty_get_value_as_string(prop);
	else recurid = "";

	hash_insert(recurid, comp, &comp_table);

    } while ((comp = icalcomponent_get_next_component(ical, kind)));


    if (kind == ICAL_VPOLL_COMPONENT) {
	recip_kind = ICAL_VOTER_PROPERTY;
	get_recipient = &icalproperty_get_voter;
    }
    else {
	recip_kind = ICAL_ATTENDEE_PROPERTY;
	get_recipient = &icalproperty_get_attendee;
    }

    /* Process each component in the iTIP reply */
    for (itip = icalcomponent_get_first_component(reply, kind);
	 itip;
	 itip = icalcomponent_get_next_component(reply, kind)) {

	/* Lookup this comp in the hash table */
	prop =
	    icalcomponent_get_first_property(itip, ICAL_RECURRENCEID_PROPERTY);
	if (prop) recurid = icalproperty_get_value_as_string(prop);
	else recurid = "";

	comp = hash_lookup(recurid, &comp_table);
	if (!comp) {
	    /* New recurrence overridden by attendee.
	       Create a new recurrence from master component. */
	    comp = icalcomponent_new_clone(hash_lookup("", &comp_table));

	    /* Add RECURRENCE-ID */
	    icalcomponent_add_property(comp, icalproperty_new_clone(prop));

	    /* Remove RRULE */
	    prop = icalcomponent_get_first_property(comp, ICAL_RRULE_PROPERTY);
	    if (prop) {
		icalcomponent_remove_property(comp, prop);
		icalproperty_free(prop);
	    }

	    /* Replace DTSTART, DTEND, SEQUENCE */
	    prop =
		icalcomponent_get_first_property(comp, ICAL_DTSTART_PROPERTY);
	    if (prop) {
		icalcomponent_remove_property(comp, prop);
		icalproperty_free(prop);
	    }
	    prop =
		icalcomponent_get_first_property(itip, ICAL_DTSTART_PROPERTY);
	    if (prop)
		icalcomponent_add_property(comp, icalproperty_new_clone(prop));

	    prop =
		icalcomponent_get_first_property(comp, ICAL_DTEND_PROPERTY);
	    if (prop) {
		icalcomponent_remove_property(comp, prop);
		icalproperty_free(prop);
	    }
	    prop =
		icalcomponent_get_first_property(itip, ICAL_DTEND_PROPERTY);
	    if (prop)
		icalcomponent_add_property(comp, icalproperty_new_clone(prop));

	    prop =
		icalcomponent_get_first_property(comp, ICAL_SEQUENCE_PROPERTY);
	    if (prop) {
		icalcomponent_remove_property(comp, prop);
		icalproperty_free(prop);
	    }
	    prop =
		icalcomponent_get_first_property(itip, ICAL_SEQUENCE_PROPERTY);
	    if (prop)
		icalcomponent_add_property(comp, icalproperty_new_clone(prop));

	    icalcomponent_add_component(ical, comp);
	}

	/* Get the sending attendee */
	att = icalcomponent_get_first_property(itip, recip_kind);
	attendee = get_recipient(att);
	param = icalproperty_get_first_parameter(att, ICAL_PARTSTAT_PARAMETER);
	if (param) partstat = icalparameter_get_partstat(param);
	param = icalproperty_get_first_parameter(att, ICAL_RSVP_PARAMETER);
	if (param) rsvp = icalparameter_get_rsvp(param);

	prop =
	    icalcomponent_get_first_property(itip, ICAL_REQUESTSTATUS_PROPERTY);
	if (prop) {
	    struct icalreqstattype rq = icalproperty_get_requeststatus(prop);
	    req_stat = icalenum_reqstat_code(rq.code);
	}

	/* Find matching attendee in existing object */
	for (prop =
		 icalcomponent_get_first_property(comp, recip_kind);
	     prop && strcmp(attendee, get_recipient(prop));
	     prop =
		 icalcomponent_get_next_property(comp, recip_kind));
	if (!prop) {
	    /* Attendee added themselves to this recurrence */
	    prop = icalproperty_new_clone(att);
	    icalcomponent_add_property(comp, prop);
	}

	/* Set PARTSTAT */
	if (partstat != ICAL_PARTSTAT_NONE) {
	    param = icalparameter_new_partstat(partstat);
	    icalproperty_set_parameter(prop, param);
	}

	/* Set RSVP */
	icalproperty_remove_parameter_by_kind(prop, ICAL_RSVP_PARAMETER);
	if (rsvp != ICAL_RSVP_NONE) {
	    param = icalparameter_new_rsvp(rsvp);
	    icalproperty_add_parameter(prop, param);
	}

	/* Set SCHEDULE-STATUS */
	param = icalparameter_new_schedulestatus(req_stat);
	icalproperty_set_parameter(prop, param);

	/* Handle VPOLL reply */
	if (kind == ICAL_VPOLL_COMPONENT) deliver_merge_vpoll_reply(comp, itip);
    }

    free_hash_table(&comp_table, NULL);

    return attendee;
}