/** Set icalcomponent X-* property.
 *
 * @param comp iCal component.
 * @param key Property name (i.e. X-EEE-WHATEVER).
 * @param value Property value.
 */
static void icomp_x_prop_set(icalcomponent *comp, const char *key, const char *value)
{
    icalproperty *iter;

    g_return_if_fail(comp != NULL);
    g_return_if_fail(key != NULL);

again:
    for (iter = icalcomponent_get_first_property(comp, ICAL_X_PROPERTY);
         iter;
         iter = icalcomponent_get_next_property(comp, ICAL_X_PROPERTY))
    {
        const char *str = icalproperty_get_x_name(iter);

        if (str && !g_strcmp0(str, key))
        {
            icalcomponent_remove_property(comp, iter);
            icalproperty_free(iter);
            goto again;
        }
    }

    if (value)
    {
        iter = icalproperty_new_x(value);
        icalproperty_set_x_name(iter, key);
        icalcomponent_add_property(comp, iter);
    }
}
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);

}
// TODO: double check this - need an example.
void ical_property_X_MS_OLK_SENDER(struct exchange2ical *exchange2ical)
{
	icalproperty *prop;
	icalparameter *param;
	char outstr[200];

	/* Sanity check */
	if (!exchange2ical->apptStateFlags) return;
	if (!(*exchange2ical->apptStateFlags & 0x1)) return;
	if (!exchange2ical->SenderName) return;

	if (exchange2ical->SenderEmailAddress) {
		snprintf(outstr, 200, "mailto:%s",exchange2ical->SenderEmailAddress);
		prop = icalproperty_new_x(outstr);
	} else {
		prop = icalproperty_new_x("invalid:nomail");
	}

	icalproperty_set_x_name(prop, "X-MS-OLK-SENDER");
	icalcomponent_add_property(exchange2ical->vevent, prop);

	param = icalparameter_new_cn(exchange2ical->SenderName);
	icalproperty_add_parameter(prop, param);
}
static icalproperty * ical_property_add_x_property_value(icalcomponent *parent, const char *propname, const char *value)
{
	icalproperty *prop;
	icalvalue *icalText;

	/* Sanity checks */
	if (!parent) return NULL;
	if (!propname) return NULL;
	if (!value) return NULL;

	icalText = icalvalue_new_text(value);
	prop = icalproperty_new_x(icalvalue_as_ical_string(icalText));
	icalvalue_free(icalText);
	icalproperty_set_x_name(prop, propname);
	icalcomponent_add_property(parent, prop);
	return prop;
}
Beispiel #5
0
static gboolean
do_mail_to_event (AsyncData *data)
{
	EClient *client;
	CamelFolder *folder = data->folder;
	GPtrArray *uids = data->uids;
	GError *error = NULL;

	client = e_client_cache_get_client_sync (data->client_cache,
		data->source, data->extension_name, 30, NULL, &error);

	/* Sanity check. */
	g_return_val_if_fail (
		((client != NULL) && (error == NULL)) ||
		((client == NULL) && (error != NULL)), TRUE);

	if (error != NULL) {
		report_error_idle (_("Cannot open calendar. %s"), error->message);
	} else if (e_client_is_readonly (E_CLIENT (client))) {
		switch (data->source_type) {
		case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
			report_error_idle (_("Selected calendar is read only, thus cannot create event there. Select other calendar, please."), NULL);
			break;
		case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
			report_error_idle (_("Selected task list is read only, thus cannot create task there. Select other task list, please."), NULL);
			break;
		case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
			report_error_idle (_("Selected memo list is read only, thus cannot create memo there. Select other memo list, please."), NULL);
			break;
		default:
			g_warn_if_reached ();
			break;
		}
	} else {
		gint i;
		ECalComponentDateTime dt, dt2;
		struct icaltimetype tt, tt2;
		struct _manage_comp *oldmc = NULL;

		#define cache_backend_prop(prop) { \
			gchar *val = NULL; \
			e_client_get_backend_property_sync (E_CLIENT (client), prop, &val, NULL, NULL); \
			g_free (val); \
		}

		/* precache backend properties, thus editor have them ready when needed */
		cache_backend_prop (CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS);
		cache_backend_prop (CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS);
		cache_backend_prop (CAL_BACKEND_PROPERTY_DEFAULT_OBJECT);
		e_client_get_capabilities (E_CLIENT (client));

		#undef cache_backend_prop

		/* set start day of the event as today, without time - easier than looking for a calendar's time zone */
		tt = icaltime_today ();
		dt.value = &tt;
		dt.tzid = NULL;

		tt2 = tt;
		icaltime_adjust (&tt2, 1, 0, 0, 0);
		dt2.value = &tt2;
		dt2.tzid = NULL;

		for (i = 0; i < (uids ? uids->len : 0); i++) {
			CamelMimeMessage *message;
			ECalComponent *comp;
			ECalComponentText text;
			icalproperty *icalprop;
			icalcomponent *icalcomp;
			struct _manage_comp *mc;

			/* retrieve the message from the CamelFolder */
			/* FIXME Not passing a GCancellable or GError. */
			message = camel_folder_get_message_sync (
				folder, g_ptr_array_index (uids, i),
				NULL, NULL);
			if (!message) {
				continue;
			}

			comp = e_cal_component_new ();

			switch (data->source_type) {
			case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_EVENT);
				break;
			case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_TODO);
				break;
			case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
				e_cal_component_set_new_vtype (comp, E_CAL_COMPONENT_JOURNAL);
				break;
			default:
				g_warn_if_reached ();
				break;
			}

			e_cal_component_set_uid (comp, camel_mime_message_get_message_id (message));
			e_cal_component_set_dtstart (comp, &dt);

			if (data->source_type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS) {
				/* make it an all-day event */
				e_cal_component_set_dtend (comp, &dt2);
			}

			/* set the summary */
			text.value = camel_mime_message_get_subject (message);
			text.altrep = NULL;
			e_cal_component_set_summary (comp, &text);

			/* set all fields */
			if (data->selected_text) {
				GSList sl;

				text.value = data->selected_text;
				text.altrep = NULL;
				sl.next = NULL;
				sl.data = &text;

				e_cal_component_set_description_list (comp, &sl);
			} else
				set_description (comp, message);

			if (data->with_attendees) {
				gchar *organizer;

				/* set actual user as organizer, to be able to change event's properties */
				organizer = set_organizer (comp, data->folder);
				set_attendees (comp, message, organizer);
				g_free (organizer);
			}

			/* set attachment files */
			set_attachments (E_CAL_CLIENT (client), comp, message);

			/* priority */
			set_priority (comp, CAMEL_MIME_PART (message));

			/* no need to increment a sequence number, this is a new component */
			e_cal_component_abort_sequence (comp);

			icalcomp = e_cal_component_get_icalcomponent (comp);

			icalprop = icalproperty_new_x ("1");
			icalproperty_set_x_name (icalprop, "X-EVOLUTION-MOVE-CALENDAR");
			icalcomponent_add_property (icalcomp, icalprop);

			mc = g_new0 (struct _manage_comp, 1);
			mc->client = g_object_ref (client);
			mc->comp = g_object_ref (comp);
			g_mutex_init (&mc->mutex);
			g_cond_init (&mc->cond);
			mc->mails_count = uids->len;
			mc->mails_done = i + 1; /* Current task */
			mc->editor_title = NULL;
			mc->can_continue = TRUE;

			if (oldmc) {
				/* Wait for user to quit the editor created in previous iteration
				 * before displaying next one */
				gboolean can_continue;
				g_mutex_lock (&oldmc->mutex);
				g_cond_wait (&oldmc->cond, &oldmc->mutex);
				g_mutex_unlock (&oldmc->mutex);
				can_continue = oldmc->can_continue;
				free_manage_comp_struct (oldmc);
				oldmc = NULL;

				if (!can_continue)
					break;
			}

			e_cal_client_get_object_sync (
				E_CAL_CLIENT (client),
				icalcomponent_get_uid (icalcomp),
				NULL, &mc->stored_comp, NULL, NULL);

			/* Prioritize ahead of GTK+ redraws. */
			g_idle_add_full (
				G_PRIORITY_HIGH_IDLE,
				(GSourceFunc) do_manage_comp_idle, mc, NULL);

			oldmc = mc;

			g_object_unref (comp);
			g_object_unref (message);

		}

		/* Wait for the last editor and then clean up */
		if (oldmc) {
			g_mutex_lock (&oldmc->mutex);
			g_cond_wait (&oldmc->cond, &oldmc->mutex);
			g_mutex_unlock (&oldmc->mutex);
			free_manage_comp_struct (oldmc);
		}
	}

	/* free memory */
	if (client != NULL)
		g_object_unref (client);
	g_ptr_array_unref (uids);
	g_object_unref (folder);

	g_object_unref (data->client_cache);
	g_object_unref (data->source);
	g_free (data->selected_text);
	g_free (data);
	data = NULL;

	if (error != NULL)
		g_error_free (error);

	return TRUE;
}
static void
process_meeting (ECalendarView *cal_view, icalparameter_partstat status)
{
	GList *selected;
	icalcomponent *clone;

	selected = e_calendar_view_get_selected_events (cal_view);
	if (selected) {
		ECalendarViewEvent *event = (ECalendarViewEvent *) selected->data;
		ECalComponent *comp = e_cal_component_new ();
		ReceiveData *r_data = g_new0 (ReceiveData, 1);
		gboolean recurring = FALSE;
		GThread *thread = NULL;
		GError *error = NULL;
		char *address = NULL;

		e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (event->comp_data->icalcomp));
		address = itip_get_comp_attendee (comp, event->comp_data->client);

		if (e_cal_component_has_recurrences (comp) || e_cal_component_is_instance (comp))
			recurring = TRUE;

		/* Free comp */
		g_object_unref (comp);
		comp = NULL;

		clone = icalcomponent_new_clone (event->comp_data->icalcomp);
		change_status (clone, address, status);

		r_data->ecal = g_object_ref (event->comp_data->client);
		r_data->icalcomp = clone;

		if (recurring) {
			gint response;
			const char *arg;

			if (status == ICAL_PARTSTAT_ACCEPTED || status == ICAL_PARTSTAT_TENTATIVE)
				arg = "accept";
			else
				arg = "decline";

			response = e_error_run (NULL, "org.gnome.evolution.mail_shared_folder:recurrence", arg, NULL);
			if (response == GTK_RESPONSE_YES) {
				icalproperty *prop;
				const char *uid = icalcomponent_get_uid (r_data->icalcomp);

				prop = icalproperty_new_x ("All");
				icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
				icalcomponent_add_property (r_data->icalcomp, prop);

				prop = icalproperty_new_x (uid);
				icalproperty_set_x_name (prop, "X-GW-RECURRENCE-KEY");
				icalcomponent_add_property (r_data->icalcomp, prop);

			} else if (response == GTK_RESPONSE_CANCEL) {
				finalize_receive_data (r_data);
				return;
			}
		}

		thread = g_thread_create ((GThreadFunc) receive_objects, r_data , FALSE, &error);
		if (!thread) {
			g_warning (G_STRLOC ": %s", error->message);
			g_error_free (error);
		}
	}
}
Beispiel #7
0
icalproperty *icalproperty_new_tzuntil(struct icaltimetype v)
{
    icalproperty *prop = icalproperty_new_x(icaltime_as_ical_string(v));
    icalproperty_set_x_name(prop, "TZUNTIL");
    return prop;
}
Beispiel #8
0
icalproperty *icalproperty_new_tzidaliasof(const char *v)
{
    icalproperty *prop = icalproperty_new_x(v);
    icalproperty_set_x_name(prop, "TZID-ALIAS-OF");
    return prop;
}
Beispiel #9
0
icalcomponent *icaltzutil_fetch_timezone(const char *location)
{
    tzinfo type_cnts;
    size_t i, num_trans, num_chars, num_leaps, num_isstd, num_isgmt;
    size_t num_types = 0;
    size_t size;
    time_t trans;
    int dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx;
    icalcomponent *std_comp = NULL;

    const char *zonedir;
    FILE *f = NULL;
    char *full_path = NULL;
    time_t *transitions = NULL;
    char *r_trans = NULL, *temp;
    int *trans_idx = NULL;
    ttinfo *types = NULL;
    char *znames = NULL;
    leap *leaps = NULL;
    char *tzid = NULL;

    time_t start, end;
    int idx, prev_idx;
    icalcomponent *tz_comp = NULL, *comp = NULL, *dst_comp;
    icalproperty *icalprop;
    icaltimetype dtstart, icaltime;
    struct icalrecurrencetype ical_recur;

    if (icaltimezone_get_builtin_tzdata()) {
        goto error;
    }

    zonedir = icaltzutil_get_zone_directory();
    if (!zonedir) {
        icalerror_set_errno(ICAL_FILE_ERROR);
        goto error;
    }

    size = strlen(zonedir) + strlen(location) + 2;
    full_path = (char *)malloc(size);
    if (full_path == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    snprintf(full_path, size, "%s/%s", zonedir, location);
    if ((f = fopen(full_path, "rb")) == 0) {
        icalerror_set_errno(ICAL_FILE_ERROR);
        goto error;
    }

    if (fseek(f, 20, SEEK_SET) != 0) {
        icalerror_set_errno(ICAL_FILE_ERROR);
        goto error;
    }

    EFREAD(&type_cnts, 24, 1, f);

    num_isgmt = (size_t)decode(type_cnts.ttisgmtcnt);
    num_leaps = (size_t)decode(type_cnts.leapcnt);
    num_chars = (size_t)decode(type_cnts.charcnt);
    num_trans = (size_t)decode(type_cnts.timecnt);
    num_isstd = (size_t)decode(type_cnts.ttisstdcnt);
    num_types = (size_t)decode(type_cnts.typecnt);

    transitions = calloc(num_trans, sizeof(time_t));
    if (transitions == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    r_trans = calloc(num_trans, 4);
    if (r_trans == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }

    EFREAD(r_trans, 4, num_trans, f);
    temp = r_trans;
    if (num_trans) {
        trans_idx = calloc(num_trans, sizeof(int));
        if (trans_idx == NULL) {
            icalerror_set_errno(ICAL_NEWFAILED_ERROR);
            goto error;
        }
        for (i = 0; i < num_trans; i++) {
            trans_idx[i] = fgetc(f);
            transitions[i] = (time_t) decode(r_trans);
            r_trans += 4;
        }
    }
    r_trans = temp;

    types = calloc(num_types, sizeof(ttinfo));
    if (types == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    for (i = 0; i < num_types; i++) {
        unsigned char a[4];
        int c;

        EFREAD(a, 4, 1, f);
        c = fgetc(f);
        types[i].isdst = (unsigned char)c;
        if ((c = fgetc(f)) < 0) {
            break;
        }
        types[i].abbr = (unsigned int)c;
        types[i].gmtoff = decode(a);
    }

    znames = (char *)malloc(num_chars);
    if (znames == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    EFREAD(znames, num_chars, 1, f);

    /* We got all the information which we need */

    leaps = calloc(num_leaps, sizeof(leap));
    if (leaps == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    for (i = 0; i < num_leaps; i++) {
        char c[4];

        EFREAD(c, 4, 1, f);
        leaps[i].transition = (time_t)decode(c);

        EFREAD(c, 4, 1, f);
        leaps[i].change = decode(c);
    }

    for (i = 0; i < num_isstd; ++i) {
        int c = getc(f);
        types[i].isstd = c != 0;
    }

    while (i < num_types) {
        types[i++].isstd = 0;
    }

    for (i = 0; i < num_isgmt; ++i) {
        int c = getc(f);

        types[i].isgmt = c != 0;
    }

    while (i < num_types) {
        types[i++].isgmt = 0;
    }

    /* Read all the contents now */

    for (i = 0; i < num_types; i++) {
        /* coverity[tainted_data] */
        types[i].zname = zname_from_stridx(znames, types[i].abbr);
    }

    if (!_s_use_exact_timezones) {
        if (num_trans != 0) {
            find_transidx(transitions, types, trans_idx, (long int)num_trans, &stdidx, &dstidx);
        } else {
            stdidx = 0;
        }
    }

    tz_comp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);

    /* Add tzid property */
    size = strlen(icaltimezone_tzid_prefix()) + strlen(location) + 1;
    tzid = (char *)malloc(size);
    if (tzid == NULL) {
        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
        goto error;
    }
    snprintf(tzid, size, "%s%s", icaltimezone_tzid_prefix(), location);
    icalprop = icalproperty_new_tzid(tzid);
    icalcomponent_add_property(tz_comp, icalprop);

    icalprop = icalproperty_new_x(location);
    icalproperty_set_x_name(icalprop, "X-LIC-LOCATION");
    icalcomponent_add_property(tz_comp, icalprop);

    if (!_s_use_exact_timezones) {
        if (stdidx != -1) {
            if (num_trans != 0) {
                zidx = trans_idx[stdidx];
            } else {
                zidx = 0;
            }

            std_comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
            icalprop = icalproperty_new_tzname(types[zidx].zname);
            icalcomponent_add_property(std_comp, icalprop);

            if (dstidx != -1) {
                zp_idx = trans_idx[stdidx-1];
            } else {
                zp_idx = zidx;
            }
            /* DTSTART localtime uses TZOFFSETFROM UTC offset */
            if (num_trans != 0) {
                trans = transitions[stdidx] + types[zp_idx].gmtoff;
            } else {
                trans = (time_t)types[zp_idx].gmtoff;
            }
            icaltime = icaltime_from_timet_with_zone(trans, 0, NULL);
            dtstart = icaltime;
            dtstart.year = 1970;
            dtstart.minute = dtstart.second = 0;
            icalprop = icalproperty_new_dtstart(dtstart);
            icalcomponent_add_property(std_comp, icalprop);

            /* If DST changes are present use RRULE */
            if (dstidx != -1) {
                icalrecurrencetype_clear(&ical_recur);
                ical_recur.freq = ICAL_YEARLY_RECURRENCE;
                ical_recur.by_month[0] = icaltime.month;
                pos = calculate_pos(icaltime);
                pos < 0 ? (sign = -1): (sign = 1);
                ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime));
                icalprop = icalproperty_new_rrule(ical_recur);
                icalcomponent_add_property(std_comp, icalprop);

                adjust_dtstart_day_to_rrule(std_comp, ical_recur);
            }
            icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff);
            icalcomponent_add_property(std_comp, icalprop);
            icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff);
            icalcomponent_add_property(std_comp, icalprop);
            icalcomponent_add_component(tz_comp, std_comp);
        } else {
            icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
        }

        if (dstidx != -1) {
            zidx = trans_idx[dstidx];
            zp_idx = trans_idx[dstidx-1];
            dst_comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
            icalprop = icalproperty_new_tzname(types[zidx].zname);
            icalcomponent_add_property(dst_comp, icalprop);

            /* DTSTART localtime uses TZOFFSETFROM UTC offset */
            trans = transitions[dstidx] + types[zp_idx].gmtoff;

            icaltime = icaltime_from_timet_with_zone(trans, 0, NULL);
            dtstart = icaltime;
            dtstart.year = 1970;
            dtstart.minute = dtstart.second = 0;
            icalprop = icalproperty_new_dtstart(dtstart);
            icalcomponent_add_property(dst_comp, icalprop);

            icalrecurrencetype_clear(&ical_recur);
            ical_recur.freq = ICAL_YEARLY_RECURRENCE;
            ical_recur.by_month[0] = icaltime.month;
            pos = calculate_pos(icaltime);
            pos < 0 ? (sign = -1): (sign = 1);
            ical_recur.by_day[0] = sign * ((abs(pos) * 8) + icaltime_day_of_week(icaltime));
            icalprop = icalproperty_new_rrule(ical_recur);
            icalcomponent_add_property(dst_comp, icalprop);

            adjust_dtstart_day_to_rrule(dst_comp, ical_recur);

            icalprop = icalproperty_new_tzoffsetfrom(types[zp_idx].gmtoff);
            icalcomponent_add_property(dst_comp, icalprop);

            icalprop = icalproperty_new_tzoffsetto(types[zidx].gmtoff);
            icalcomponent_add_property(dst_comp, icalprop);

            icalcomponent_add_component(tz_comp, dst_comp);
        }
    } else { /*exact vtimezones*/
        prev_idx = 0;
        if (num_trans == 0) {
            prev_idx = idx = 0;
        } else {
            idx = trans_idx[0];
        }
        start = 0;
        for (i = 1; i < num_trans; i++, start = end) {
            prev_idx = idx;
            idx = trans_idx[i];
            end = transitions[i] + types[prev_idx].gmtoff;
            /* don't bother starting until the epoch */
            if (0 > end)
                continue;

            if (types[prev_idx].isdst) {
                comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
            } else {
                comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
            }
            icalprop = icalproperty_new_tzname(types[prev_idx].zname);
            icalcomponent_add_property(comp, icalprop);
            dtstart = icaltime_from_timet_with_zone(start, 0, NULL);
            icalprop = icalproperty_new_dtstart(dtstart);
            icalcomponent_add_property(comp, icalprop);
            icalprop = icalproperty_new_tzoffsetfrom(types[idx].gmtoff);
            icalcomponent_add_property(comp, icalprop);
            icalprop = icalproperty_new_tzoffsetto(types[prev_idx].gmtoff);
            icalcomponent_add_property(comp, icalprop);
            icalcomponent_add_component(tz_comp, comp);
        }
        /* finally, add a last zone with no end date */
        if (types[idx].isdst) {
            comp = icalcomponent_new(ICAL_XDAYLIGHT_COMPONENT);
        } else {
            comp = icalcomponent_new(ICAL_XSTANDARD_COMPONENT);
        }
        icalprop = icalproperty_new_tzname(types[idx].zname);
        icalcomponent_add_property(comp, icalprop);
        dtstart = icaltime_from_timet_with_zone(start, 0, NULL);
        icalprop = icalproperty_new_dtstart(dtstart);
        icalcomponent_add_property(comp, icalprop);
        icalprop = icalproperty_new_tzoffsetfrom(types[prev_idx].gmtoff);
        icalcomponent_add_property(comp, icalprop);
        icalprop = icalproperty_new_tzoffsetto(types[idx].gmtoff);
        icalcomponent_add_property(comp, icalprop);
        icalcomponent_add_component(tz_comp, comp);
    }

  error:
    if (f)
        fclose(f);

    if (full_path)
        free(full_path);

    if (transitions)
        free(transitions);

    if (r_trans)
        free(r_trans);

    if (trans_idx)
        free(trans_idx);

    if (types) {
        for (i = 0; i < num_types; i++) {
            if (types[i].zname) {
                free(types[i].zname);
            }
        }
        free(types);
    }

    if (znames)
        free(znames);

    if (leaps)
        free(leaps);

    if (tzid)
        free(tzid);

    return tz_comp;
}
void
e_sendoptions_utils_fill_component (ESendOptionsDialog *sod, ECalComponent *comp)
{
	int i = 1;
	icalproperty *prop;
	icalcomponent *icalcomp;
	ESendOptionsGeneral *gopts;
	ESendOptionsStatusTracking *sopts;

	gopts = sod->data->gopts;
	sopts = sod->data->sopts;

	e_cal_component_set_sequence (comp, &i);
	icalcomp = e_cal_component_get_icalcomponent (comp);

	if (e_sendoptions_get_need_general_options (sod)) {
		prop = icalproperty_new_x ((const char *) g_strdup_printf ("%d", gopts->priority));
		icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-PRIORITY");
		icalcomponent_add_property (icalcomp, prop);

		if (gopts->reply_enabled) {
			if (gopts->reply_convenient)
				prop = icalproperty_new_x ("convenient");
			else
				prop = icalproperty_new_x ((const char *) g_strdup_printf ( "%d", gopts->reply_within));
			icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-REPLY");
			icalcomponent_add_property (icalcomp, prop);
		}

		if (gopts->expiration_enabled && gopts->expire_after) {
			prop = icalproperty_new_x ((const char *) g_strdup_printf ( "%d", gopts->expire_after));
			icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-EXPIRE");
			icalcomponent_add_property (icalcomp, prop);
		}

		if (gopts->delay_enabled) {
			struct icaltimetype temp;
			char *str;

			icaltimezone *zone = calendar_config_get_icaltimezone ();
			temp = icaltime_from_timet_with_zone (gopts->delay_until, FALSE, zone);

			str = icaltime_as_ical_string (temp);
			prop = icalproperty_new_x (str);
			g_free (str);
			icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-DELAY");
			icalcomponent_add_property (icalcomp, prop);
		}
	}

	if (sopts->tracking_enabled)
		prop = icalproperty_new_x ((const char *) g_strdup_printf ( "%d", sopts->track_when));
	else
		prop = icalproperty_new_x ("0");

	icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-TRACKINFO");
	icalcomponent_add_property (icalcomp, prop);


	prop = icalproperty_new_x ((const char *) g_strdup_printf ("%d", sopts->opened));
	icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-OPENED");
	icalcomponent_add_property (icalcomp, prop);

	prop = icalproperty_new_x ((const char *) g_strdup_printf ("%d", sopts->accepted));
	icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-ACCEPTED");
	icalcomponent_add_property (icalcomp, prop);

	prop = icalproperty_new_x ((const char *) g_strdup_printf ("%d", sopts->declined));
	icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-DECLINED");
	icalcomponent_add_property (icalcomp, prop);

	prop = icalproperty_new_x ((const char *) g_strdup_printf ("%d", sopts->completed));
	icalproperty_set_x_name (prop, "X-EVOLUTION-OPTIONS-COMPLETED");
	icalcomponent_add_property (icalcomp, prop);
}
icalcomponent*
icaltzutil_fetch_timezone (const char *location)
{
	int ret = 0;
	FILE *f;
	tzinfo type_cnts;
	unsigned int num_trans, num_types, num_chars, num_leaps, num_isstd, num_isgmt;
	time_t *transitions = NULL;
	time_t trans;
	int *trans_idx = NULL, dstidx = -1, stdidx = -1, pos, sign, zidx, zp_idx, i;
	ttinfo *types = NULL;
	char *znames = NULL, *full_path, *tzid, *r_trans, *temp;
	leap *leaps = NULL;
	icalcomponent *tz_comp = NULL, *dst_comp = NULL, *std_comp = NULL;
	icalproperty *icalprop;
	icaltimetype dtstart, icaltime;
	struct icalrecurrencetype ical_recur;
	       
	if (!zdir) 
		set_zone_directory ();
	
	full_path = (char *) malloc (strlen (zdir) + strlen (location) + 2);
	sprintf (full_path,"%s/%s",zdir, location);

	if ((f = fopen (full_path, "rb")) == 0) {
		icalerror_set_errno (ICAL_FILE_ERROR);
		free (full_path);
		return NULL;
	}

	if ((ret = fseek (f, 20, SEEK_SET)) != 0) {
		icalerror_set_errno (ICAL_FILE_ERROR);
		goto error;	
	}

	EFREAD(&type_cnts, 24, 1, f);

	num_isgmt = decode (type_cnts.ttisgmtcnt);
	num_leaps = decode (type_cnts.leapcnt);
	num_chars = decode (type_cnts.charcnt);
	num_trans = decode (type_cnts.timecnt);
	num_isstd = decode (type_cnts.ttisstdcnt);
	num_types = decode (type_cnts.typecnt);

	transitions = calloc (num_trans, sizeof (time_t));
	r_trans = calloc (num_trans, 4);
	EFREAD(r_trans, 4, num_trans, f);
	temp = r_trans;	

	if (num_trans) {
		trans_idx = calloc (num_trans, sizeof (int));
		for (i = 0; i < num_trans; i++) {
			trans_idx [i] = fgetc (f);
			transitions [i] = decode (r_trans);
			r_trans += 4;
		}
	}
	
	free (temp);

	types = calloc (num_types, sizeof (ttinfo));
	for (i = 0; i < num_types; i++) {
		unsigned char a [4];
		int c;

		EFREAD(a, 4, 1, f);
		c = fgetc (f);
		types [i].isdst = c;
		if((c = fgetc (f)) < 0) {
		   c = 0;
		   break;
		}
		types [i].abbr = c;
		types [i].gmtoff = decode (a);
	}

	znames = (char *) malloc (num_chars);
	EFREAD(znames, num_chars, 1, f);

	/* We got all the information which we need */

	leaps = calloc (num_leaps, sizeof (leap));
	for (i = 0; i < num_leaps; i++) {
		char c [4];

		EFREAD (c, 4, 1, f);
		leaps [i].transition = decode (c);

		EFREAD (c, 4, 1, f);
		leaps [i].change = decode (c);
	}

	for (i = 0; i < num_isstd; ++i) {
		int c = getc (f);
		types [i].isstd = c != 0;
	}

	while (i < num_types)
		types [i++].isstd = 0;

	for (i = 0; i <  num_isgmt; ++i) {
		int c = getc (f);
		types [i].isgmt = c != 0;
	}

	while (i < num_types)
		types [i++].isgmt = 0;

	/* Read all the contents now */

	for (i = 0; i < num_types; i++) 
		types [i].zname = zname_from_stridx (znames, types [i].abbr);

	if (num_trans != 0)
		find_transidx (transitions, types, trans_idx, num_trans, &stdidx, &dstidx);
	else
		stdidx = 0;

	tz_comp = icalcomponent_new (ICAL_VTIMEZONE_COMPONENT);

	/* Add tzid property */
	tzid = (char *) malloc (strlen (ical_tzid_prefix) + strlen (location) + 8);
	sprintf (tzid, "%sTzfile/%s", ical_tzid_prefix, location);
	icalprop = icalproperty_new_tzid (tzid);
	icalcomponent_add_property (tz_comp, icalprop);
	free (tzid);

	icalprop = icalproperty_new_x (location);
	icalproperty_set_x_name (icalprop, "X-LIC-LOCATION");
	icalcomponent_add_property (tz_comp, icalprop);
	
	if (stdidx != -1) {
		if (num_trans != 0)
			zidx = trans_idx [stdidx];
		else 
			zidx = 0;

		std_comp = icalcomponent_new (ICAL_XSTANDARD_COMPONENT);
		icalprop = icalproperty_new_tzname (types [zidx].zname);
		icalcomponent_add_property (std_comp, icalprop);

		if (dstidx != -1)
			zp_idx = trans_idx [stdidx-1]; 
		else
			zp_idx = zidx;
		/* DTSTART localtime uses TZOFFSETFROM UTC offset */
		trans = transitions [stdidx] + types [zp_idx].gmtoff;
		icaltime = icaltime_from_timet (trans, 0);
		dtstart = icaltime;
		dtstart.year = 1970;
		dtstart.minute = dtstart.second = 0;
		icalprop = icalproperty_new_dtstart (dtstart);
		icalcomponent_add_property (std_comp, icalprop);

		/* If DST changes are present use RRULE */
		if (dstidx != -1) {
			icalrecurrencetype_clear (&ical_recur);
			ical_recur.freq = ICAL_YEARLY_RECURRENCE;
			ical_recur.by_month [0] = icaltime.month;
			pos = calculate_pos (icaltime);
			pos < 0 ? (sign = -1): (sign = 1);
			ical_recur.by_day [0] = sign * ((abs (pos) * 8) + icaltime_day_of_week (icaltime));
			icalprop = icalproperty_new_rrule (ical_recur);
			icalcomponent_add_property (std_comp, icalprop);

			adjust_dtstart_day_to_rrule (std_comp, ical_recur);
		}
        icalprop = icalproperty_new_tzoffsetfrom (types [zp_idx].gmtoff);
        icalcomponent_add_property (std_comp, icalprop);

		icalprop = icalproperty_new_tzoffsetto (types [zidx].gmtoff);
		icalcomponent_add_property (std_comp, icalprop);

		icalcomponent_add_component (tz_comp, std_comp);
	} else 
		icalerror_set_errno (ICAL_MALFORMEDDATA_ERROR);
	
	if (dstidx != -1) {
		zidx = trans_idx [dstidx];
		zp_idx = trans_idx [dstidx-1];
		dst_comp = icalcomponent_new (ICAL_XDAYLIGHT_COMPONENT);
		icalprop = icalproperty_new_tzname (types [zidx].zname);
		icalcomponent_add_property (dst_comp, icalprop);

		/* DTSTART localtime uses TZOFFSETFROM UTC offset */
		trans = transitions [dstidx] + types [zp_idx].gmtoff;
		icaltime = icaltime_from_timet (trans, 0);
		dtstart = icaltime;
		dtstart.year = 1970;
		dtstart.minute = dtstart.second = 0;
		icalprop = icalproperty_new_dtstart (dtstart);
		icalcomponent_add_property (dst_comp, icalprop);

		icalrecurrencetype_clear (&ical_recur);
		ical_recur.freq = ICAL_YEARLY_RECURRENCE;
		ical_recur.by_month [0] = icaltime.month;
		pos = calculate_pos (icaltime);
		pos < 0 ? (sign = -1): (sign = 1);
		ical_recur.by_day [0] = sign * ((abs (pos) * 8) + icaltime_day_of_week (icaltime));
		icalprop = icalproperty_new_rrule (ical_recur);
		icalcomponent_add_property (dst_comp, icalprop);

		adjust_dtstart_day_to_rrule (dst_comp, ical_recur);

		icalprop = icalproperty_new_tzoffsetfrom (types [zp_idx].gmtoff);
		icalcomponent_add_property (dst_comp, icalprop);

		icalprop = icalproperty_new_tzoffsetto (types [zidx].gmtoff);
		icalcomponent_add_property (dst_comp, icalprop);

		icalcomponent_add_component (tz_comp, dst_comp);
	}

error:
	if (f)
		fclose  (f);

	if (transitions)
		free (transitions);
	if (trans_idx)
		free (trans_idx);
	if (types) {
		for (i = 0; i < num_types; i++) 
			if (types [i].zname)
				free (types [i].zname);
		free (types);
	}
	if (znames)
		free (znames);
	free (full_path);
	if (leaps)
		free (leaps);

	return tz_comp;
}