static char *
scalix_appointment_to_string (ScalixObject * object)
{
    ScalixAppointment *app;
    char *str;

    app = SCALIX_APPOINTMENT (object);
    e_cal_component_commit_sequence (E_CAL_COMPONENT (app));

    str = e_cal_component_get_as_string (E_CAL_COMPONENT (app));

    return str;
}
static gboolean
deserialize (ScalixObject * object, const char *string)
{
    ScalixAppointmentPrivate *priv;
    icalcomponent *icomp, *subcomp;
    icalcomponent_kind kind;
    icaltimezone *zone;

    priv = SCALIX_APPOINTMENT_GET_PRIVATE (SCALIX_APPOINTMENT (object));

    icomp = icalparser_parse_string (string);

    if (icalcomponent_isa (icomp) != ICAL_VCALENDAR_COMPONENT) {
        g_warning ("No VCALENAR while deserializing! (%s)\n", string);
        icalcomponent_free (icomp);
        return FALSE;
    }

    /* Grab the timezone if any */
    subcomp = icalcomponent_get_first_component (icomp,
                                                 ICAL_VTIMEZONE_COMPONENT);
    if (subcomp != NULL) {
        zone = icaltimezone_new ();
        icalcomponent_remove_component (icomp, subcomp);
        if (icaltimezone_set_component (zone, subcomp))
            priv->timezone = zone;
    }

    kind = ICAL_VEVENT_COMPONENT;
    /* Grab the main VEVENT */
    subcomp = icalcomponent_get_first_component (icomp, kind);

    if (subcomp == NULL) {
        icalcomponent_free (icomp);
        return FALSE;
    }

    icalcomponent_remove_component (icomp, subcomp);
    e_cal_component_set_icalcomponent (E_CAL_COMPONENT (object), subcomp);
    e_cal_component_commit_sequence (E_CAL_COMPONENT (object));

    priv->exceptions = NULL;
    while ((subcomp = icalcomponent_get_next_component (icomp, kind))) {
        icalcomponent_remove_component (icomp, subcomp);
        priv->exceptions = g_slist_prepend (priv->exceptions, subcomp);
    }

    icalcomponent_free (icomp);

    return TRUE;
}
void
scalix_appointment_set (ScalixAppointment * comp,
                        const char *key, const char *value)
{
    icalcomponent *icomp;
    icalproperty *icalprop;

    e_cal_component_commit_sequence (E_CAL_COMPONENT (comp));

    icomp = e_cal_component_get_icalcomponent (E_CAL_COMPONENT (comp));
    icalprop = icalproperty_new_x (value);
    icalproperty_set_x_name (icalprop, key);
    icalcomponent_add_property (icomp, icalprop);

}
static gchar *
test_get_free_busy (ECal *client)
{
	/* TODO uses NULL for users and currently specific to file backend. */
	GList *l, *freebusy = NULL;
	GError *error = NULL;
	icaltimezone *utc;
	time_t start, end;

	utc = icaltimezone_get_utc_timezone ();
	start = time_from_isodate ("20040212T000000Z");
	end = time_add_day_with_zone (start, 2, utc);

	if (!e_cal_get_free_busy (client, NULL, start, end, &freebusy, &error)) {
		cl_printf (client, "Test free/busy : Could not retrieve free busy information :  %s\n", error->message);
		return error->message;
	}
	if (freebusy) {
		cl_printf (client, "Printing free busy information\n");
		for (l = freebusy; l; l = l->next) {
			gchar *comp_string;
			ECalComponent *comp = E_CAL_COMPONENT (l->data);

			comp_string = e_cal_component_get_as_string (comp);
			cl_printf (client, "%s\n\n", comp_string);
			g_object_unref (comp);
			g_free (comp_string);
		}
	}
	else {
		cl_printf (client, "free_busy was returned but NULL");
	}
	return NULL;
}
ScalixAppointment *
scalix_appointment_new (const char *calobj)
{
    ScalixAppointment *comp;
    icalcomponent *icalcomp = NULL;
    ECalComponent *ecomp;

    if (calobj != NULL) {
        icalcomp = icalparser_parse_string (calobj);

        if (icalcomp == NULL) {
            return NULL;
        }

    }

    comp = g_object_new (SCALIX_TYPE_APPOINTMENT, NULL);
    ecomp = E_CAL_COMPONENT (comp);

    if (icalcomp != NULL) {
        e_cal_component_set_icalcomponent (ecomp, icalcomp);
    }

    return comp;
}
void
scalix_appointment_unset (ScalixAppointment * comp, const char *key)
{
    icalcomponent *icomp;
    icalproperty *icalprop;
    const char *x_val;
    GSList *list, *iter;

    list = NULL;
    icomp = e_cal_component_get_icalcomponent (E_CAL_COMPONENT (comp));
    icalprop = icalcomponent_get_first_property (icomp, ICAL_X_PROPERTY);

    while (icalprop) {
        const char *x_name;

        x_name = icalproperty_get_x_name (icalprop);
        x_val = icalproperty_get_x (icalprop);

        if (!strcmp (x_name, key)) {
            list = g_slist_prepend (list, icalprop);
        }

        icalprop = icalcomponent_get_next_property (icomp, ICAL_X_PROPERTY);
    }

    for (iter = list; iter; iter = iter->next) {
        icalprop = iter->data;
        icalcomponent_remove_property (icomp, icalprop);
        icalproperty_free (icalprop);
    }

    return;
}
Example #7
0
/**
 * e_cal_util_generate_alarms_for_list:
 * @comps: (element-type ECalComponent): List of #ECalComponent<!-- -->s
 * @start: Start time
 * @end: End time
 * @omit: Alarm types to omit
 * @comp_alarms: (out) (transfer full) (element-type ECalComponentAlarms): List
 * to be returned
 * @resolve_tzid: (closure user_data) (scope call): Callback for resolving
 * timezones
 * @user_data: (closure): Data to be passed to the resolve_tzid callback
 * @default_timezone: The timezone used to resolve DATE and floating DATE-TIME
 * values.
 *
 * Iterates through all the components in the @comps list and generates alarm
 * instances for them; putting them in the @comp_alarms list.
 *
 * Returns: the number of elements it added to the list
 */
gint
e_cal_util_generate_alarms_for_list (GList *comps,
                                     time_t start,
                                     time_t end,
                                     ECalComponentAlarmAction *omit,
                                     GSList **comp_alarms,
                                     ECalRecurResolveTimezoneFn resolve_tzid,
                                     gpointer user_data,
                                     icaltimezone *default_timezone)
{
	GList *l;
	gint n;

	n = 0;

	for (l = comps; l; l = l->next) {
		ECalComponent *comp;
		ECalComponentAlarms *alarms;

		comp = E_CAL_COMPONENT (l->data);
		alarms = e_cal_util_generate_alarms_for_comp (
			comp, start, end, omit, resolve_tzid,
			user_data, default_timezone);

		if (alarms) {
			*comp_alarms = g_slist_prepend (*comp_alarms, alarms);
			n++;
		}
	}

	return n;
}
gboolean
scalix_appointment_get (ScalixAppointment * comp, const char *key, char **value)
{
    icalcomponent *icomp;
    icalproperty *icalprop;
    const char *x_val;

    icomp = e_cal_component_get_icalcomponent (E_CAL_COMPONENT (comp));
    icalprop = icalcomponent_get_first_property (icomp, ICAL_X_PROPERTY);

    while (icalprop) {
        const char *x_name;

        x_name = icalproperty_get_x_name (icalprop);
        x_val = icalproperty_get_x (icalprop);

        if (!strcmp (x_name, key)) {
            break;
        }

        icalprop = icalcomponent_get_next_property (icomp, ICAL_X_PROPERTY);
    }

    if (icalprop) {
        *value = g_strdup (x_val);
        return TRUE;
    }

    *value = NULL;

    return FALSE;
}
static ScalixObject *
iclone (ScalixObject * object)
{
    char *str;
    ScalixObject *cloned;

    g_return_val_if_fail (object != NULL, NULL);

    e_cal_component_commit_sequence (E_CAL_COMPONENT (object));
    str = e_cal_component_get_as_string (E_CAL_COMPONENT (object));

    g_assert (str != NULL);

    cloned = SCALIX_OBJECT (scalix_appointment_new (str));

    g_free (str);

    return cloned;
}
static void
scalix_appointment_init (ScalixAppointment * comp)
{
    ECalComponent *ecomp;
    ScalixAppointmentPrivate *priv;

    priv = SCALIX_APPOINTMENT_GET_PRIVATE (comp);

    ecomp = E_CAL_COMPONENT (comp);

    e_cal_component_set_new_vtype (ecomp, E_CAL_COMPONENT_EVENT);

    priv->exceptions = NULL;
}
Example #11
0
/* Get_objects_in_range handler for the file backend */
static void
e_cal_backend_http_get_object_list (ECalBackendSync *backend,
                                    EDataCal *cal,
                                    GCancellable *cancellable,
                                    const gchar *sexp,
                                    GSList **objects,
                                    GError **perror)
{
	ECalBackendHttp *cbhttp;
	ECalBackendHttpPrivate *priv;
	GSList *components, *l;
	ECalBackendSExp *cbsexp;
	ETimezoneCache *timezone_cache;
	time_t occur_start = -1, occur_end = -1;
	gboolean prunning_by_time;

	cbhttp = E_CAL_BACKEND_HTTP (backend);
	priv = cbhttp->priv;

	timezone_cache = E_TIMEZONE_CACHE (backend);

	if (!priv->store) {
		g_propagate_error (perror, EDC_ERROR (NoSuchCal));
		return;
	}

	/* process all components in the cache */
	cbsexp = e_cal_backend_sexp_new (sexp);

	*objects = NULL;
	prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (
		cbsexp,
		&occur_start,
		&occur_end);

	components = prunning_by_time ?
		e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
		: e_cal_backend_store_get_components (priv->store);

	for (l = components; l != NULL; l = g_slist_next (l)) {
		if (e_cal_backend_sexp_match_comp (cbsexp, E_CAL_COMPONENT (l->data), timezone_cache)) {
			*objects = g_slist_append (*objects, e_cal_component_get_as_string (l->data));
		}
	}

	g_slist_foreach (components, (GFunc) g_object_unref, NULL);
	g_slist_free (components);
	g_object_unref (cbsexp);
}
static gboolean
set_ical_from_mime_part (CamelMimePart * part, ScalixObject * object)
{
    CamelDataWrapper *content;
    CamelStream *stream;
    GByteArray *data;
    icalcomponent *icomp = NULL;
    icalcomponent *subcomp = NULL;
    ScalixAppointmentPrivate *priv;

    priv = SCALIX_APPOINTMENT_GET_PRIVATE (SCALIX_APPOINTMENT (object));

    content = camel_medium_get_content_object (CAMEL_MEDIUM (part));

    data = g_byte_array_new ();
    stream = camel_stream_mem_new_with_byte_array (data);
    camel_data_wrapper_decode_to_stream (content, stream);

    if (data == NULL || data->data == NULL) {
        g_print ("Found corrupt ical data\n");
        return FALSE;
    }

    icomp = icalparser_parse_string ((const char *) data->data);

    if (icalcomponent_isa (icomp) != ICAL_VCALENDAR_COMPONENT) {
        icalcomponent_free (icomp);
        return FALSE;
    }

    /* Grab the timezone if any */
    subcomp = icalcomponent_get_first_component (icomp,
                                                 ICAL_VTIMEZONE_COMPONENT);
    if (subcomp != NULL) {
        icaltimezone *zone;

        zone = icaltimezone_new ();
        icaltimezone_set_component (zone, subcomp);
        priv->timezone = zone;
    }

    /* Grab the main VEVENT */
    subcomp = icalcomponent_get_first_component (icomp, ICAL_VEVENT_COMPONENT);

    e_cal_component_set_icalcomponent (E_CAL_COMPONENT (object), subcomp);

    return TRUE;
}
static char *
serialize (ScalixObject * object)
{
    ScalixAppointmentPrivate *priv;
    icalcomponent *icomp, *toplevel_comp;
    ECalComponent *comp;
    GSList *iter;
    char *result = NULL;

    priv = SCALIX_APPOINTMENT_GET_PRIVATE (SCALIX_APPOINTMENT (object));

    scalix_appointment_unset (SCALIX_APPOINTMENT (object),
                              "X-SCALIX-DESCRIPTION-CHANGED");

    comp = E_CAL_COMPONENT (object);

    e_cal_component_commit_sequence (comp);
    icomp = e_cal_component_get_icalcomponent (comp);

    if (icomp) {
        toplevel_comp = e_cal_util_new_top_level ();
        /* add timezone if one exists */
        if (priv->timezone) {
            icalcomponent_add_component (toplevel_comp,
                                         icalcomponent_new_clone
                                         (icaltimezone_get_component
                                          (priv->timezone)));
        }
        /* add the main vevent */
        icalcomponent_add_component (toplevel_comp,
                                     icalcomponent_new_clone (icomp));
        /* add exceptions if they exist */
        for (iter = priv->exceptions; iter; iter = iter->next) {
            icalcomponent_add_component (toplevel_comp,
                                         icalcomponent_new_clone ((icalcomponent*) iter->data));
        }
        result = icalcomponent_as_ical_string (toplevel_comp);

        if (result != NULL) {
            result = g_strdup (result);
        }

        icalcomponent_free (toplevel_comp);
    }

    
    return result;
}
gint
main (gint argc,
      gchar **argv)
{
	ECal *ecal;
	GList *l, *objects;

	g_type_init ();

	if (argc < 3) {
		printf ("usage: test-search <uid> <query>\n");
		exit (0);
	}

	/* FIXME We don't build ECals from URIs anymore. */
	/* ecal = e_cal_new_from_uri (argv[1], E_CAL_SOURCE_TYPE_EVENT); */
	ecal = NULL;

	if (!e_cal_open (ecal, TRUE, NULL)) {
		printf ("failed to open calendar\n");
		exit (0);
	}

	if (!e_cal_get_object_list_as_comp (ecal, argv[2], &objects, NULL)) {
		printf ("failed to get objects\n");
		exit (0);
	}

	printf ("Received %d objects\n", g_list_length (objects));
	for (l = objects; l; l = l->next) {
		ECalComponent *comp = E_CAL_COMPONENT (l->data);
		gchar *str;

		str = e_cal_component_get_as_string (comp);
		printf ("%s\n", str);

		g_free (str);
		g_object_unref (comp);
	}

	g_list_free (objects);

	g_object_unref (ecal);

	return 0;
}
static void
scalix_appointment_get_property (GObject * object,
                                 guint prop_id,
                                 GValue * value, GParamSpec * pspec)
{
    ScalixAppointment *app;
    char *str;
    const char *uid;
    ScalixAppointmentPrivate *priv;

    priv = SCALIX_APPOINTMENT_GET_PRIVATE (SCALIX_APPOINTMENT (object));

    app = SCALIX_APPOINTMENT (object);

    switch (prop_id) {

    case PROP_ICAL:
        str = scalix_appointment_to_string (SCALIX_OBJECT (object));
        g_value_take_string (value, str);
        break;

    case PROP_TIMEZONE:
        g_value_set_pointer (value, priv->timezone);
        break;

    case PROP_EXCEPTIONS:
        g_value_set_pointer (value, priv->exceptions);
        break;

    case PROP_UID:
        e_cal_component_get_uid (E_CAL_COMPONENT (app), &uid);
        g_value_set_string (value, uid);
        break;

    case PROP_IPM_TYPE:
        g_value_set_int (value, IPM_APPOINTMENT);
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);

    }
}
static gboolean
scalix_appointment_from_string (ScalixObject * object, const char *string)
{
    icalcomponent *icomp, *subcomp;

    icomp = icalparser_parse_string (string);
    if (icalcomponent_isa (icomp) == ICAL_VCALENDAR_COMPONENT) {
        subcomp = icalcomponent_get_first_component (icomp,
                                                     ICAL_VEVENT_COMPONENT);
        icalcomponent_remove_component (icomp, subcomp);
        icalcomponent_free (icomp);
        icomp = subcomp;

    }

    e_cal_component_set_icalcomponent (E_CAL_COMPONENT (object), icomp);

    return TRUE;
}
/** Wrapper for e_cal_backend_cache_get_components_by_uid().
 *
 * Get master components and all detached instances for given UID.
 * Components/detached instances with cache state
 * E_CAL_COMPONENT_CACHE_STATE_REMOVED will be omitted.
 *
 * @param cb 3E calendar backend.
 * @param cache Calendar backend cache object.
 * @param uid UID of the calendar components.
 *
 * @return List of matching ECalComponent objects.
 */
GSList *e_cal_backend_3e_cache_get_components_by_uid(ECalBackend3e *cb, ECalBackendCache *cache, const char *uid)
{
    GSList *iter, *iter_next;
    GSList *list;

    g_static_rw_lock_reader_lock(&cb->priv->cache_lock);
    list = e_cal_backend_cache_get_components_by_uid(cache, uid);
    g_static_rw_lock_reader_unlock(&cb->priv->cache_lock);
    for (iter = list; iter; iter = iter_next)
    {
        ECalComponent *comp = E_CAL_COMPONENT(iter->data);
        iter_next = iter->next;

        if (e_cal_component_get_cache_state(comp) == E_CAL_COMPONENT_CACHE_STATE_REMOVED)
        {
            list = g_slist_remove_link(list, iter);
            g_object_unref(comp);
        }
    }

    return list;
}
/** Sync cache changes to the server and unmark them.
 *
 * @param cb 3E calendar backend.
 *
 * @return TRUE on success.
 *
 * @todo Conflict resolution.
 */
gboolean e_cal_backend_3e_sync_cache_to_server(ECalBackend3e *cb)
{
    GError *local_err = NULL;
    GList *components, *iter;

    if (!e_cal_backend_3e_open_connection(cb, &local_err))
    {
        g_warning("Sync failed. Can't open connection to the 3e server. (%s)", local_err ? local_err->message : "Unknown error");
        g_clear_error(&local_err);
        return FALSE;
    }

    sync_timezones_to_server(cb);

    g_static_rw_lock_reader_lock(&cb->priv->cache_lock);
    components = e_cal_backend_cache_get_components(cb->priv->cache);
    g_static_rw_lock_reader_unlock(&cb->priv->cache_lock);

    for (iter = components; iter && !e_cal_backend_3e_sync_should_stop(cb); iter = iter->next)
    {
        ECalComponent *comp = E_CAL_COMPONENT(iter->data);
        ECalComponent *remote_comp;
        ECalComponentId *id = e_cal_component_get_id(comp);
        ECalComponentCacheState state = e_cal_component_get_cache_state(comp);
        /* remove client properties before sending component to the server */
        e_cal_component_set_x_property(comp, "X-EVOLUTION-STATUS", NULL);
        e_cal_component_set_cache_state(comp, E_CAL_COMPONENT_CACHE_STATE_NONE);
        e_cal_component_set_x_property(comp, "X-3E-DELETED", NULL);
        remote_comp = e_cal_component_clone(comp);
        gboolean attachments_converted = e_cal_backend_3e_convert_attachment_uris_to_remote(cb, remote_comp);
        char *remote_object = e_cal_component_get_as_string(remote_comp);
        char *object = e_cal_component_get_as_string(comp);

        if (!attachments_converted)
        {
            goto next;
        }

        if (state == E_CAL_COMPONENT_CACHE_STATE_CREATED || state == E_CAL_COMPONENT_CACHE_STATE_MODIFIED)
        {
            if (!e_cal_backend_3e_upload_attachments(cb, remote_comp, &local_err))
            {
                e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e attachemnts sync failure", local_err);
                g_clear_error(&local_err);
                goto next;
            }
        }

        switch (state)
        {
        case E_CAL_COMPONENT_CACHE_STATE_CREATED:
        {
            ESClient_addObject(cb->priv->conn, cb->priv->calspec, remote_object, &local_err);
            if (local_err)
            {
                e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err);
                g_clear_error(&local_err);
                break;
            }

            char *new_object = e_cal_component_get_as_string(comp);
            e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), object, new_object);
            g_free(new_object);

            g_static_rw_lock_writer_lock(&cb->priv->cache_lock);
            e_cal_backend_cache_put_component(cb->priv->cache, comp);
            g_static_rw_lock_writer_unlock(&cb->priv->cache_lock);
            break;
        }

        case E_CAL_COMPONENT_CACHE_STATE_MODIFIED:
        {
            ESClient_updateObject(cb->priv->conn, cb->priv->calspec, remote_object, &local_err);
            if (local_err)
            {
                e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err);
                g_clear_error(&local_err);
                break;
            }

            char *new_object = e_cal_component_get_as_string(comp);
            e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), object, new_object);
            g_free(new_object);

            g_static_rw_lock_writer_lock(&cb->priv->cache_lock);
            e_cal_backend_cache_put_component(cb->priv->cache, comp);
            g_static_rw_lock_writer_unlock(&cb->priv->cache_lock);
            break;
        }

        case E_CAL_COMPONENT_CACHE_STATE_REMOVED:
        {
            char *oid = id->rid ? g_strdup_printf("%s@%s", id->uid, id->rid) : g_strdup(id->uid);
            ESClient_deleteObject(cb->priv->conn, cb->priv->calspec, oid, &local_err);
            g_free(oid);
            if (local_err)
            {
                // ignore the error if component doesn't exist anymore
                if (local_err->code == ES_XMLRPC_ERROR_UNKNOWN_COMPONENT)
                {
                    g_clear_error(&local_err);
                    local_err = NULL;
                }
                else 
                {
                    e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err);
                    g_clear_error(&local_err);
                    break;
                }
            }

            g_static_rw_lock_writer_lock(&cb->priv->cache_lock);
            e_cal_backend_cache_remove_component(cb->priv->cache, id->uid, id->rid);
            g_static_rw_lock_writer_unlock(&cb->priv->cache_lock);
            break;
        }

        case E_CAL_COMPONENT_CACHE_STATE_NONE:
        default:
            break;
        }

next:
        g_object_unref(comp);
        g_object_unref(remote_comp);
        e_cal_component_free_id(id);
        g_free(object);
        g_free(remote_object);
    }

    g_list_free(components);

    e_cal_backend_3e_close_connection(cb);

    return TRUE;
}
gboolean
scalix_appointment_init_from_mime_message (ScalixObject * object,
                                           CamelMimeMessage * msg)
{
    const char *msgid;
    const char *attachment_store;
    const char *mime_type, *alternative_mime_type;
    const char *content_disposition;
    const char *mime_filename;
    const char *cid;
    const char *cuid;
    const char *attachment_file_url;
    GSList *attachments = NULL;
    GSList *attachments_new = NULL;
    GSList *siter = NULL;
    CamelMimePart *part, *alternative;
    CamelMultipart *multipart, *nested_multipart;
    CamelDataWrapper *content, *alternative_content;
    int i, j, num_parts, num_alternatives;
    gboolean found_ical = FALSE;

    attachment_store =
        g_object_get_data (G_OBJECT (object), "attachment-store");

    part = CAMEL_MIME_PART (msg);
    content = camel_medium_get_content_object (CAMEL_MEDIUM (part));

    if (content == NULL) {
        return FALSE;
    }

    mime_type = camel_content_type_simple (content->mime_type);

    if (CAMEL_IS_MULTIPART (content)) {
        multipart = (CamelMultipart *) content;
        num_parts = (int) camel_multipart_get_number (multipart);

        for (i = 0; i < num_parts; i++) {
            part = camel_multipart_get_part (multipart, i);
            content = camel_medium_get_content_object (CAMEL_MEDIUM (part));
            mime_type = camel_content_type_simple (content->mime_type);
            mime_filename = camel_mime_part_get_filename (part);
            content_disposition = camel_mime_part_get_disposition (part);

            if (CAMEL_IS_MULTIPART (content)) {
                nested_multipart = (CamelMultipart *) content;
                num_alternatives =
                    (int) camel_multipart_get_number (nested_multipart);
                for (j = 0; j < num_alternatives; j++) {
                    alternative =
                        camel_multipart_get_part (nested_multipart, j);
                    alternative_content =
                        camel_medium_get_content_object (CAMEL_MEDIUM
                                                         (alternative));
                    alternative_mime_type =
                        camel_content_type_simple (alternative_content->
                                                   mime_type);
                    if (g_str_equal (alternative_mime_type, "text/calendar")
                        && found_ical == FALSE) {
                        if (set_ical_from_mime_part (alternative, object) ==
                            TRUE) {
                            e_cal_component_get_uid (E_CAL_COMPONENT (object),
                                                     &cuid);
                            e_cal_component_get_attachment_list (E_CAL_COMPONENT
                                                                 (object),
                                                                 &attachments);
                            /* we are only interested in the first ical body part */
                            found_ical = TRUE;
                        }
                    }
                }
            } else if (g_str_equal (mime_type, "text/calendar")
                       && found_ical == FALSE) {
                if (set_ical_from_mime_part (part, object) == TRUE) {
                    e_cal_component_get_uid (E_CAL_COMPONENT (object), &cuid);
                    e_cal_component_get_attachment_list (E_CAL_COMPONENT
                                                         (object),
                                                         &attachments);
                    /* we are only interested in the first ical body part */
                    found_ical = TRUE;
                }
            } else if (content_disposition
                       && strcmp (content_disposition, "attachment") == 0) {
                cid = camel_mime_part_get_content_id (part);
                if (cid != NULL) {
                    for (siter = attachments; siter; siter = siter->next) {
                        if (strstr (siter->data, cid) ==
                            (char *) (siter->data) + 4) {
                            attachment_file_url =
                                save_attachment (part, cuid, attachment_store);
                            if (attachment_file_url != NULL) {
                                attachments_new =
                                    g_slist_append (attachments_new,
                                                    g_strdup
                                                    (attachment_file_url));
                            }
                        }
                    }
                }
            } else {
                g_print ("XXXXX Unhandled mime part: %s\n", mime_type);
            }
        }
    } else {
        /* just a simple ical message */
        if (g_str_equal (mime_type, "text/calendar")) {
            set_ical_from_mime_part (part, object);
        }
    }

    if (attachments_new != NULL) {
        e_cal_component_set_attachment_list (E_CAL_COMPONENT (object),
                                             attachments_new);
    }

    msgid = camel_mime_message_get_message_id (msg);

    scalix_appointment_unset (SCALIX_APPOINTMENT (object), X_SCALIX_MSG_ID);

    scalix_appointment_set (SCALIX_APPOINTMENT (object),
                            X_SCALIX_MSG_ID, msgid);

    return TRUE;
}
CamelMimeMessage *
scalix_appointment_to_mime_message (ScalixObject * object)
{
    CamelMimeMessage *message;
    CamelMultipart *multipart;
    CamelMimePart *part;
    CamelMedium *medium;
    CamelStream *stream;
    CamelDataWrapper *wrapper;
    ECalComponentDateTime dtstart, dtend;
    ECalComponent *comp;
    ECalComponentText text;
    icalcomponent_kind kind;
    icalcomponent *icalcomp, *toplevel_comp;
    icaltimezone *zone = NULL;
    GSList *attachment_list = NULL;
    GSList *attachment_list_new = NULL;
    GSList *siter = NULL;
    GList *part_list = NULL;
    GList *iter = NULL;
    char *msgid;
    char *str, *meeting_status;
    const char *ouid = NULL;
    char *file_contents = NULL;
    char *full_path, *filename, *mime_filename;
    char *cid;
    int size;

    g_object_get (SCALIX_APPOINTMENT (object), "timezone", &zone, NULL);

    comp = E_CAL_COMPONENT (scalix_object_clone (object));
    message = camel_mime_message_new ();
    medium = CAMEL_MEDIUM (message);

    camel_medium_add_header (medium, "X-Scalix-Class", "IPM.Appointment");

    /* Preserve msg id if there is already one */
    if (scalix_appointment_get (SCALIX_APPOINTMENT (comp),
                                X_SCALIX_MSG_ID, &msgid)) {

        scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_MSG_ID);

    } else {
        msgid = camel_header_msgid_generate ();
    }

    camel_mime_message_set_message_id (message, msgid);

    /* subject */
    e_cal_component_get_summary (comp, &text);

    if (text.value != NULL) {
        camel_mime_message_set_subject (message, text.value);
    }

    /* start day */
    e_cal_component_get_dtstart (comp, &dtstart);

    if (!icaltime_get_timezone (*dtstart.value))
        icaltime_set_timezone (dtstart.value,
                               icaltimezone_get_builtin_timezone_from_tzid
                               (dtstart.tzid));

    /* end day */
    e_cal_component_get_dtend (comp, &dtend);

    if (!icaltime_get_timezone (*dtend.value))
        icaltime_set_timezone (dtend.value,
                               icaltimezone_get_builtin_timezone_from_tzid
                               (dtend.tzid));

    /* set From: and Sender: */
    if (e_cal_component_has_organizer (comp)) {
        ECalComponentOrganizer organizer;

        e_cal_component_get_organizer (comp, &organizer);
        if (!strncasecmp (organizer.value, "MAILTO:", 7)) {
            camel_medium_add_header (medium, "Sender", organizer.value + 7);
            camel_medium_add_header (medium, "From", organizer.value + 7);
        }
    }

    /* set the appropriate recipient headers from the recipient table */
    if (e_cal_component_has_attendees (comp)
        && e_cal_component_has_organizer (comp)) {
        GSList *iter, *attendees = NULL;
        CamelInternetAddress *recipients_to = NULL;
        CamelInternetAddress *recipients_cc = NULL;

        meeting_status = "1";

        e_cal_component_get_attendee_list (comp, &attendees);

        for (iter = attendees; iter; iter = iter->next) {
            ECalComponentAttendee *attendee = iter->data;
            const char *mail = NULL;

            /* attendee entries must start with MAILTO: */
            if (strncasecmp (attendee->value, "MAILTO:", 7)) {
                continue;
            }

            mail = attendee->value + 7;

            if (attendee->role == ICAL_ROLE_REQPARTICIPANT) {
                if (recipients_to == NULL) {
                    recipients_to = camel_internet_address_new ();
                }
                camel_internet_address_add (recipients_to, attendee->cn, mail);
            } else if (attendee->role == ICAL_ROLE_OPTPARTICIPANT) {
                if (recipients_cc == NULL) {
                    recipients_cc = camel_internet_address_new ();
                }
                camel_internet_address_add (recipients_cc, attendee->cn, mail);
            } else {
                continue;
            }
        }

        if (recipients_to != NULL) {
            camel_mime_message_set_recipients (message, "To", recipients_to);
            camel_object_unref (recipients_to);
        }

        if (recipients_cc != NULL) {
            camel_mime_message_set_recipients (message, "Cc", recipients_cc);
            camel_object_unref (recipients_cc);
        }
    } else {
        meeting_status = "0";
    }

    /* Clear properties */
    scalix_appointment_unset (SCALIX_APPOINTMENT (comp), X_SCALIX_IMAP_UID);
    /* Render the text/calendar  */
    e_cal_component_commit_sequence (comp);
    icalcomp = e_cal_component_get_icalcomponent (comp);

    kind = icalcomponent_isa (icalcomp);
    if (kind != ICAL_VCALENDAR_COMPONENT) {
        /* If its not a VCALENDAR, make it one to simplify below */
        toplevel_comp = e_cal_util_new_top_level ();
        icalcomponent_add_component (toplevel_comp, icalcomp);
        icalcomp = toplevel_comp;
    }

    /* set METHOD to PUSBLISH */
    icalcomponent_set_method (icalcomp, ICAL_METHOD_PUBLISH);

    /* Add the VTIMEZONE components for start- and/or end-times */
    if (zone) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component (zone));
    } else if (dtstart.tzid) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component
                                     (icaltimezone_get_builtin_timezone_from_tzid
                                      (dtstart.tzid)));
    }

    if (dtstart.tzid && dtend.tzid && strcmp (dtstart.tzid, dtend.tzid) != 0) {
        icalcomponent_add_component (icalcomp,
                                     icaltimezone_get_component
                                     (icaltimezone_get_builtin_timezone_from_tzid
                                      (dtend.tzid)));
    }

    /* FIXME: do we leek icalcomponents here? */

    if (e_cal_component_has_attachments (comp)) {

        multipart = camel_multipart_new ();
        camel_multipart_set_boundary (multipart, NULL);

        e_cal_component_get_uid (comp, &ouid);
        e_cal_component_get_attachment_list (comp, &attachment_list);

        for (siter = attachment_list; siter; siter = siter->next) {

            if (siter->data == NULL)
                continue;

            if (strstr (siter->data, "file://") != siter->data)
                continue;

            full_path = ((char *) siter->data) + strlen ("file://");
            filename = g_strrstr (full_path, "/") + 1;
            mime_filename = filename + strlen (ouid) + 1;

            size = 0;
            file_contents = get_file_contents (full_path, &size);

            if (file_contents == NULL)
                continue;

            stream = camel_stream_mem_new_with_buffer (file_contents, size);
            wrapper = camel_data_wrapper_new ();
            camel_data_wrapper_construct_from_stream (wrapper, stream);
            camel_object_unref (stream);

            part = camel_mime_part_new ();
            camel_medium_set_content_object (CAMEL_MEDIUM (part), wrapper);
            camel_mime_part_set_filename (part, mime_filename);
            camel_mime_part_set_encoding (part, CAMEL_TRANSFER_ENCODING_BASE64);

            cid = camel_header_msgid_generate ();
            camel_mime_part_set_content_id (part, cid);
            camel_mime_part_set_description (part, mime_filename);
            camel_mime_part_set_disposition (part, "attachment");
            part_list = g_list_append (part_list, part);

            attachment_list_new = g_slist_append (attachment_list_new,
                                                  g_strdup_printf ("CID:%s",
                                                                   cid));
            g_free (cid);
        }

        e_cal_component_set_attachment_list (comp, attachment_list_new);
        str = icalcomponent_as_ical_string (icalcomp);

        part = camel_mime_part_new ();

        camel_mime_part_set_content (part,
                                     str,
                                     strlen (str),
                                     "text/calendar; method=PUBLISH; charset=UTF-8");

        part_list = g_list_prepend (part_list, part);

        for (iter = part_list; iter; iter = iter->next) {
            part = (CamelMimePart *) iter->data;
            camel_multipart_add_part (multipart, part);
            camel_object_unref (part);
        }

        camel_medium_set_content_object (CAMEL_MEDIUM (message),
                                         CAMEL_DATA_WRAPPER (multipart));
        camel_object_unref (multipart);

        g_slist_free (attachment_list);
        g_slist_free (attachment_list_new);
        g_list_free (part_list);

    } else {
        str = icalcomponent_as_ical_string (icalcomp);

        camel_mime_part_set_content (CAMEL_MIME_PART (message),
                                     str,
                                     strlen (str),
                                     "text/calendar; method=PUBLISH; charset=UTF-8");
    }

    scalix_appointment_set (SCALIX_APPOINTMENT (object),
                            X_SCALIX_MSG_ID, msgid);

    return message;
}