"
"
%s
"
"
%s
",
primary, secondary);
itip_view_set_error (view, error, save_btn);
g_free (error);
}
static gboolean
extract_itip_data (EMailPartItip *pitip,
ItipView *view,
gboolean *have_alarms)
{
EShell *shell;
EShellSettings *shell_settings;
icalproperty *prop;
icalcomponent_kind kind = ICAL_NO_COMPONENT;
icalcomponent *tz_comp;
icalcompiter tz_iter;
icalcomponent *alarm_comp;
icalcompiter alarm_iter;
ECalComponent *comp;
gboolean use_default_reminder;
shell = e_shell_get_default ();
shell_settings = e_shell_get_shell_settings (shell);
if (!pitip->vcalendar) {
set_itip_error (view,
_("The calendar attached is not valid"),
_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."),
FALSE);
return FALSE;
}
pitip->top_level = e_cal_util_new_top_level ();
pitip->main_comp = icalparser_parse_string (pitip->vcalendar);
if (pitip->main_comp == NULL || !is_icalcomp_valid (pitip->main_comp)) {
set_itip_error (view,
_("The calendar attached is not valid"),
_("The message claims to contain a calendar, but the calendar is not a valid iCalendar."),
FALSE);
if (pitip->main_comp) {
icalcomponent_free (pitip->main_comp);
pitip->main_comp = NULL;
}
return FALSE;
}
prop = icalcomponent_get_first_property (pitip->main_comp, ICAL_METHOD_PROPERTY);
if (prop == NULL) {
pitip->method = ICAL_METHOD_PUBLISH;
} else {
pitip->method = icalproperty_get_method (prop);
}
tz_iter = icalcomponent_begin_component (pitip->main_comp, ICAL_VTIMEZONE_COMPONENT);
while ((tz_comp = icalcompiter_deref (&tz_iter)) != NULL) {
icalcomponent *clone;
clone = icalcomponent_new_clone (tz_comp);
icalcomponent_add_component (pitip->top_level, clone);
icalcompiter_next (&tz_iter);
}
pitip->iter = icalcomponent_begin_component (pitip->main_comp, ICAL_ANY_COMPONENT);
pitip->ical_comp = icalcompiter_deref (&pitip->iter);
if (pitip->ical_comp != NULL) {
kind = icalcomponent_isa (pitip->ical_comp);
if (kind != ICAL_VEVENT_COMPONENT
&& kind != ICAL_VTODO_COMPONENT
&& kind != ICAL_VFREEBUSY_COMPONENT
&& kind != ICAL_VJOURNAL_COMPONENT)
pitip->ical_comp = get_next (&pitip->iter);
}
if (pitip->ical_comp == NULL) {
set_itip_error (view,
_("The item in the calendar is not valid"),
_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
FALSE);
return FALSE;
}
switch (icalcomponent_isa (pitip->ical_comp)) {
case ICAL_VEVENT_COMPONENT:
pitip->type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS;
pitip->has_organizer = icalcomponent_get_first_property (pitip->ical_comp, ICAL_ORGANIZER_PROPERTY) != NULL;
if (icalcomponent_get_first_property (pitip->ical_comp, ICAL_ATTENDEE_PROPERTY) == NULL) {
/* no attendees: assume that that this is not a meeting and organizer doesn't want a reply */
pitip->no_reply_wanted = TRUE;
} else {
/*
* if we have attendees, then find_to_address() will check for our RSVP
* and set no_reply_wanted=TRUE if RSVP=FALSE for the current user
*/
}
break;
case ICAL_VTODO_COMPONENT:
pitip->type = E_CAL_CLIENT_SOURCE_TYPE_TASKS;
break;
case ICAL_VJOURNAL_COMPONENT:
pitip->type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS;
break;
default:
set_itip_error (view,
_("The item in the calendar is not valid"),
_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
FALSE);
return FALSE;
}
pitip->total = icalcomponent_count_components (pitip->main_comp, ICAL_VEVENT_COMPONENT);
pitip->total += icalcomponent_count_components (pitip->main_comp, ICAL_VTODO_COMPONENT);
pitip->total += icalcomponent_count_components (pitip->main_comp, ICAL_VFREEBUSY_COMPONENT);
pitip->total += icalcomponent_count_components (pitip->main_comp, ICAL_VJOURNAL_COMPONENT);
if (pitip->total > 1) {
set_itip_error (view,
_("The calendar attached contains multiple items"),
_("To process all of these items, the file should be saved and the calendar imported"),
TRUE);
} if (pitip->total > 0) {
pitip->current = 1;
} else {
pitip->current = 0;
}
if (icalcomponent_isa (pitip->ical_comp) != ICAL_VJOURNAL_COMPONENT) {
gchar *my_address;
prop = NULL;
comp = e_cal_component_new ();
e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (pitip->ical_comp));
my_address = itip_get_comp_attendee (pitip->registry, comp, NULL);
g_object_unref (comp);
comp = NULL;
if (!prop)
prop = find_attendee (pitip->ical_comp, my_address);
if (!prop)
prop = find_attendee_if_sentby (pitip->ical_comp, my_address);
if (prop) {
icalparameter *param;
const gchar * delfrom;
if ((param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER))) {
delfrom = icalparameter_get_delegatedfrom (param);
pitip->delegator_address = g_strdup (itip_strip_mailto (delfrom));
}
}
g_free (my_address);
prop = NULL;
/* Determine any delegate sections */
prop = icalcomponent_get_first_property (pitip->ical_comp, ICAL_X_PROPERTY);
while (prop) {
const gchar *x_name, *x_val;
x_name = icalproperty_get_x_name (prop);
x_val = icalproperty_get_x (prop);
if (!strcmp (x_name, "X-EVOLUTION-DELEGATOR-CALENDAR-UID"))
pitip->calendar_uid = g_strdup (x_val);
else if (!strcmp (x_name, "X-EVOLUTION-DELEGATOR-CALENDAR-URI"))
g_warning (G_STRLOC ": X-EVOLUTION-DELEGATOR-CALENDAR-URI used");
else if (!strcmp (x_name, "X-EVOLUTION-DELEGATOR-ADDRESS"))
pitip->delegator_address = g_strdup (x_val);
else if (!strcmp (x_name, "X-EVOLUTION-DELEGATOR-NAME"))
pitip->delegator_name = g_strdup (x_val);
prop = icalcomponent_get_next_property (pitip->ical_comp, ICAL_X_PROPERTY);
}
/* Strip out procedural alarms for security purposes */
alarm_iter = icalcomponent_begin_component (pitip->ical_comp, ICAL_VALARM_COMPONENT);
while ((alarm_comp = icalcompiter_deref (&alarm_iter)) != NULL) {
icalproperty *p;
icalcompiter_next (&alarm_iter);
p = icalcomponent_get_first_property (alarm_comp, ICAL_ACTION_PROPERTY);
if (!p || icalproperty_get_action (p) == ICAL_ACTION_PROCEDURE)
icalcomponent_remove_component (pitip->ical_comp, alarm_comp);
icalcomponent_free (alarm_comp);
}
if (have_alarms) {
alarm_iter = icalcomponent_begin_component (pitip->ical_comp, ICAL_VALARM_COMPONENT);
*have_alarms = icalcompiter_deref (&alarm_iter) != NULL;
}
}
pitip->comp = e_cal_component_new ();
if (!e_cal_component_set_icalcomponent (pitip->comp, pitip->ical_comp)) {
g_object_unref (pitip->comp);
pitip->comp = NULL;
set_itip_error (view,
_("The item in the calendar is not valid"),
_("The message does contain a calendar, but the calendar contains no events, tasks or free/busy information"),
FALSE);
return FALSE;
};
/* Add default reminder if the config says so */
use_default_reminder = e_shell_settings_get_boolean (
shell_settings, "cal-use-default-reminder");
if (use_default_reminder) {
ECalComponentAlarm *acomp;
gint interval;
EDurationType units;
ECalComponentAlarmTrigger trigger;
interval = e_shell_settings_get_int (
shell_settings, "cal-default-reminder-interval");
units = e_shell_settings_get_int (
shell_settings, "cal-default-reminder-units");
acomp = e_cal_component_alarm_new ();
e_cal_component_alarm_set_action (acomp, E_CAL_COMPONENT_ALARM_DISPLAY);
trigger.type = E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START;
memset (&trigger.u.rel_duration, 0, sizeof (trigger.u.rel_duration));
trigger.u.rel_duration.is_neg = TRUE;
switch (units) {
case E_DURATION_MINUTES:
trigger.u.rel_duration.minutes = interval;
break;
case E_DURATION_HOURS:
trigger.u.rel_duration.hours = interval;
break;
case E_DURATION_DAYS:
trigger.u.rel_duration.days = interval;
break;
default:
g_assert_not_reached ();
}
e_cal_component_alarm_set_trigger (acomp, trigger);
e_cal_component_add_alarm (pitip->comp, acomp);
e_cal_component_alarm_free (acomp);
}
find_from_address (pitip, pitip->ical_comp);
find_to_address (pitip, pitip->ical_comp, NULL);
return TRUE;
}
struct _opencal_msg {
MailMsg base;
gchar *command; /* command line to run */
};
static gchar *
open_calendar__desc (struct _opencal_msg *m,
gint complete)
{
return g_strdup (_("Opening calendar"));
}
static void
open_calendar__exec (struct _opencal_msg *m,
GCancellable *cancellable,
GError **error)
{
if (!g_spawn_command_line_async (m->command, NULL)) {
g_warning ("Could not launch %s", m->command);
}
}
static void
open_calendar__free (struct _opencal_msg *m)
{
g_free (m->command);
m->command = NULL;
}
static MailMsgInfo open_calendar_info = {
sizeof (struct _opencal_msg),
(MailMsgDescFunc) open_calendar__desc,
(MailMsgExecFunc) open_calendar__exec,
(MailMsgDoneFunc) NULL,
(MailMsgFreeFunc) open_calendar__free,
};
static gboolean
idle_open_cb (gpointer data)
{
EMailPartItip *pitip = data;
struct _opencal_msg *m;
gchar *start, *end;
start = isodate_from_time_t (pitip->start_time);
end = isodate_from_time_t (pitip->end_time);
m = mail_msg_new (&open_calendar_info);
m->command = g_strdup_printf ("evolution \"calendar:///?startdate=%s&enddate=%s\"", start, end);
mail_msg_slow_ordered_push (m);
g_free (start);
g_free (end);
return FALSE;
}
static void
view_response_cb (ItipView *view,
ItipViewResponse response,
gpointer data)
{
EMailPartItip *pitip = data;
gboolean status = FALSE;
icalproperty *prop;
ECalComponentTransparency trans;
if (response == ITIP_VIEW_RESPONSE_SAVE) {
save_vcalendar_cb (pitip);
return;
}
pitip->can_delete_invitation_from_cache = FALSE;
if (pitip->method == ICAL_METHOD_PUBLISH || pitip->method == ICAL_METHOD_REQUEST) {
if (itip_view_get_free_time_check_state (view))
e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_TRANSPARENT);
else
e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
} else {
e_cal_component_get_transparency (pitip->comp, &trans);
if (trans == E_CAL_COMPONENT_TRANSP_NONE)
e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
}
if (!pitip->to_address && pitip->current_client != NULL)
e_client_get_backend_property_sync (E_CLIENT (pitip->current_client), CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS, &pitip->to_address, NULL, NULL);
/* check if it is a recur instance (no master object) and
* add a property */
if (itip_view_get_recur_check_state (view)) {
prop = icalproperty_new_x ("All");
icalproperty_set_x_name (prop, "X-GW-RECUR-INSTANCES-MOD-TYPE");
icalcomponent_add_property (pitip->ical_comp, prop);
}
switch (response) {
case ITIP_VIEW_RESPONSE_ACCEPT:
if (pitip->type != E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
status = change_status (
pitip->registry,
pitip->ical_comp,
pitip->to_address,
ICAL_PARTSTAT_ACCEPTED);
else
status = TRUE;
if (status) {
e_cal_component_rescan (pitip->comp);
pitip->can_delete_invitation_from_cache = TRUE;
update_item (pitip, view, response);
}
break;
case ITIP_VIEW_RESPONSE_TENTATIVE:
status = change_status (
pitip->registry,
pitip->ical_comp,
pitip->to_address,
ICAL_PARTSTAT_TENTATIVE);
if (status) {
e_cal_component_rescan (pitip->comp);
pitip->can_delete_invitation_from_cache = TRUE;
update_item (pitip, view, response);
}
break;
case ITIP_VIEW_RESPONSE_DECLINE:
if (pitip->type != E_CAL_CLIENT_SOURCE_TYPE_MEMOS)
status = change_status (
pitip->registry,
pitip->ical_comp,
pitip->to_address,
ICAL_PARTSTAT_DECLINED);
else {
prop = icalproperty_new_x ("1");
icalproperty_set_x_name (prop, "X-GW-DECLINED");
icalcomponent_add_property (pitip->ical_comp, prop);
status = TRUE;
}
if (status) {
e_cal_component_rescan (pitip->comp);
pitip->can_delete_invitation_from_cache = TRUE;
update_item (pitip, view, response);
}
break;
case ITIP_VIEW_RESPONSE_UPDATE:
update_attendee_status (pitip, view);
break;
case ITIP_VIEW_RESPONSE_CANCEL:
update_item (pitip, view, response);
break;
case ITIP_VIEW_RESPONSE_REFRESH:
send_item (pitip, view);
break;
case ITIP_VIEW_RESPONSE_OPEN:
g_idle_add (idle_open_cb, pitip);
return;
default:
break;
}
}
static gboolean
check_is_instance (icalcomponent *icalcomp)
{
icalproperty *icalprop;
icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
while (icalprop) {
const gchar *x_name;
x_name = icalproperty_get_x_name (icalprop);
if (!strcmp (x_name, "X-GW-RECURRENCE-KEY")) {
return TRUE;
}
icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
}
return FALSE;
}
static gboolean
in_proper_folder (ESourceRegistry *registry,
CamelFolder *folder)
{
EShell *shell;
EShellBackend *shell_backend;
EMailBackend *backend;
EMailSession *session;
MailFolderCache *folder_cache;
gboolean res = TRUE;
CamelFolderInfoFlags flags = 0;
if (!folder)
return FALSE;
shell = e_shell_get_default ();
shell_backend = e_shell_get_backend_by_name (shell, "mail");
backend = E_MAIL_BACKEND (shell_backend);
session = e_mail_backend_get_session (backend);
folder_cache = e_mail_session_get_folder_cache (session);
if (mail_folder_cache_get_folder_info_flags (folder_cache, folder, &flags)) {
/* it should be neither trash nor junk folder, */
res = ((flags & CAMEL_FOLDER_TYPE_MASK) != CAMEL_FOLDER_TYPE_TRASH &&
(flags & CAMEL_FOLDER_TYPE_MASK) != CAMEL_FOLDER_TYPE_JUNK &&
/* it can be Inbox */
( (flags & CAMEL_FOLDER_TYPE_MASK) == CAMEL_FOLDER_TYPE_INBOX ||
/* or any other virtual folder */
CAMEL_IS_VEE_FOLDER (folder) ||
/* or anything else except of sent, outbox or drafts folder */
(!em_utils_folder_is_sent (registry, folder) &&
!em_utils_folder_is_outbox (registry, folder) &&
!em_utils_folder_is_drafts (registry, folder))
));
} else {
/* cannot check for Inbox folder here */
res = (folder->folder_flags & (CAMEL_FOLDER_IS_TRASH | CAMEL_FOLDER_IS_JUNK)) == 0 && (
(CAMEL_IS_VEE_FOLDER (folder)) || (
!em_utils_folder_is_sent (registry, folder) &&
!em_utils_folder_is_outbox (registry, folder) &&
!em_utils_folder_is_drafts (registry, folder)));
}
return res;
}
void
itip_view_init_view (ItipView *view)
{
EShell *shell;
EShellSettings *shell_settings;
ESourceRegistry *registry;
ECalComponentText text;
ECalComponentOrganizer organizer;
ECalComponentDateTime datetime;
icaltimezone *from_zone, *to_zone;
GString *gstring = NULL;
GSList *list, *l;
icalcomponent *icalcomp;
const gchar *string, *org;
gint i;
gboolean response_enabled;
gboolean have_alarms = FALSE;
EMailPartItip *info;
info = view->priv->itip_part;
g_return_if_fail (info != NULL);
shell = e_shell_get_default ();
registry = e_shell_get_registry (shell);
shell_settings = e_shell_get_shell_settings (shell);
info->registry = g_object_ref (registry);
/* Reset current client before initializing view */
info->current_client = NULL;
/* Initialize the ecal hashes */
for (i = 0; i < E_CAL_CLIENT_SOURCE_TYPE_LAST; i++)
info->clients[i] = g_hash_table_new_full (
(GHashFunc) g_str_hash,
(GEqualFunc) g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
/* FIXME Handle multiple VEVENTS with the same UID, ie detached instances */
if (!extract_itip_data (info, view, &have_alarms))
return;
response_enabled = in_proper_folder (registry, info->folder);
if (!response_enabled) {
itip_view_set_mode (view, ITIP_VIEW_MODE_HIDE_ALL);
} else {
itip_view_set_show_inherit_alarm_check (
view,
have_alarms && (info->method == ICAL_METHOD_PUBLISH || info->method == ICAL_METHOD_REQUEST));
switch (info->method) {
case ICAL_METHOD_PUBLISH:
case ICAL_METHOD_REQUEST:
/*
* Treat meeting request (sent by organizer directly) and
* published evend (forwarded by organizer or attendee) alike:
* if the event has an organizer, then it can be replied to and
* we show the "accept/tentative/decline" choice.
* Otherwise only show "accept".
*/
itip_view_set_mode (view,
info->has_organizer ?
ITIP_VIEW_MODE_REQUEST :
ITIP_VIEW_MODE_PUBLISH);
break;
case ICAL_METHOD_REPLY:
itip_view_set_mode (view, ITIP_VIEW_MODE_REPLY);
break;
case ICAL_METHOD_ADD:
itip_view_set_mode (view, ITIP_VIEW_MODE_ADD);
break;
case ICAL_METHOD_CANCEL:
itip_view_set_mode (view, ITIP_VIEW_MODE_CANCEL);
break;
case ICAL_METHOD_REFRESH:
itip_view_set_mode (view, ITIP_VIEW_MODE_REFRESH);
break;
case ICAL_METHOD_COUNTER:
itip_view_set_mode (view, ITIP_VIEW_MODE_COUNTER);
break;
case ICAL_METHOD_DECLINECOUNTER:
itip_view_set_mode (view, ITIP_VIEW_MODE_DECLINECOUNTER);
break;
case ICAL_METHOD_X :
/* Handle appointment requests from Microsoft Live. This is
* a best-at-hand-now handling. Must be revisited when we have
* better access to the source of such meetings */
info->method = ICAL_METHOD_REQUEST;
itip_view_set_mode (view, ITIP_VIEW_MODE_REQUEST);
break;
default:
return;
}
}
itip_view_set_item_type (view, info->type);
if (response_enabled) {
switch (info->method) {
case ICAL_METHOD_REQUEST:
/* FIXME What about the name? */
itip_view_set_delegator (view, info->delegator_name ? info->delegator_name : info->delegator_address);
case ICAL_METHOD_PUBLISH:
case ICAL_METHOD_ADD:
case ICAL_METHOD_CANCEL:
case ICAL_METHOD_DECLINECOUNTER:
itip_view_set_show_update_check (view, FALSE);
/* An organizer sent this */
e_cal_component_get_organizer (info->comp, &organizer);
org = organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value);
itip_view_set_organizer (view, org);
if (organizer.sentby)
itip_view_set_organizer_sentby (
view, itip_strip_mailto (organizer.sentby));
if (info->my_address) {
if (!(organizer.value && !g_ascii_strcasecmp (itip_strip_mailto (organizer.value), info->my_address))
&& !(organizer.sentby && !g_ascii_strcasecmp (itip_strip_mailto (organizer.sentby), info->my_address))
&& (info->to_address && g_ascii_strcasecmp (info->to_address, info->my_address)))
itip_view_set_proxy (view, info->to_name ? info->to_name : info->to_address);
}
break;
case ICAL_METHOD_REPLY:
case ICAL_METHOD_REFRESH:
case ICAL_METHOD_COUNTER:
itip_view_set_show_update_check (view, TRUE);
/* An attendee sent this */
e_cal_component_get_attendee_list (info->comp, &list);
if (list != NULL) {
ECalComponentAttendee *attendee;
attendee = list->data;
itip_view_set_attendee (view, attendee->cn ? attendee->cn : itip_strip_mailto (attendee->value));
if (attendee->sentby)
itip_view_set_attendee_sentby (view, itip_strip_mailto (attendee->sentby));
if (info->my_address) {
if (!(attendee->value && !g_ascii_strcasecmp (itip_strip_mailto (attendee->value), info->my_address))
&& !(attendee->sentby && !g_ascii_strcasecmp (itip_strip_mailto (attendee->sentby), info->my_address))
&& (info->from_address && g_ascii_strcasecmp (info->from_address, info->my_address)))
itip_view_set_proxy (view, info->from_name ? info->from_name : info->from_address);
}
e_cal_component_free_attendee_list (list);
}
break;
default:
g_assert_not_reached ();
break;
}
}
e_cal_component_get_summary (info->comp, &text);
itip_view_set_summary (view, text.value ? text.value : C_("cal-itip", "None"));
e_cal_component_get_location (info->comp, &string);
itip_view_set_location (view, string);
/* Status really only applies for REPLY */
if (response_enabled && info->method == ICAL_METHOD_REPLY) {
e_cal_component_get_attendee_list (info->comp, &list);
if (list != NULL) {
ECalComponentAttendee *a = list->data;
switch (a->status) {
case ICAL_PARTSTAT_ACCEPTED:
itip_view_set_status (view, _("Accepted"));
break;
case ICAL_PARTSTAT_TENTATIVE:
itip_view_set_status (view, _("Tentatively Accepted"));
break;
case ICAL_PARTSTAT_DECLINED:
itip_view_set_status (view, _("Declined"));
break;
case ICAL_PARTSTAT_DELEGATED:
itip_view_set_status (view, _("Delegated"));
break;
default:
itip_view_set_status (view, _("Unknown"));
}
}
e_cal_component_free_attendee_list (list);
}
if (info->method == ICAL_METHOD_REPLY
|| info->method == ICAL_METHOD_COUNTER
|| info->method == ICAL_METHOD_DECLINECOUNTER) {
/* FIXME Check spec to see if multiple comments are actually valid */
/* Comments for iTIP are limited to one per object */
e_cal_component_get_comment_list (info->comp, &list);
if (list) {
ECalComponentText *text = list->data;
if (text->value) {
gchar *html;
html = camel_text_to_html (
text->value,
CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES,
0);
itip_view_set_comment (view, html);
g_free (html);
}
}
e_cal_component_free_text_list (list);
}
e_cal_component_get_description_list (info->comp, &list);
for (l = list; l; l = l->next) {
ECalComponentText *text = l->data;
if (!gstring && text->value)
gstring = g_string_new (text->value);
else if (text->value)
g_string_append_printf (gstring, "\n\n%s", text->value);
}
e_cal_component_free_text_list (list);
if (gstring) {
gchar *html;
html = camel_text_to_html (
gstring->str,
CAMEL_MIME_FILTER_TOHTML_CONVERT_NL |
CAMEL_MIME_FILTER_TOHTML_CONVERT_SPACES |
CAMEL_MIME_FILTER_TOHTML_CONVERT_URLS |
CAMEL_MIME_FILTER_TOHTML_MARK_CITATION |
CAMEL_MIME_FILTER_TOHTML_CONVERT_ADDRESSES,
0);
itip_view_set_description (view, html);
g_string_free (gstring, TRUE);
g_free (html);
}
to_zone = e_shell_settings_get_pointer (shell_settings, "cal-timezone");
e_cal_component_get_dtstart (info->comp, &datetime);
info->start_time = 0;
if (datetime.value) {
struct tm start_tm;
/* If the timezone is not in the component, guess the local time */
/* Should we guess if the timezone is an olsen name somehow? */
if (datetime.value->is_utc)
from_zone = icaltimezone_get_utc_timezone ();
else if (!datetime.value->is_utc && datetime.tzid)
from_zone = icalcomponent_get_timezone (info->top_level, datetime.tzid);
else
from_zone = NULL;
start_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
itip_view_set_start (view, &start_tm, datetime.value->is_date);
info->start_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
}
icalcomp = e_cal_component_get_icalcomponent (info->comp);
/* Set the recurrence id */
if (check_is_instance (icalcomp) && datetime.value) {
ECalComponentRange *recur_id;
struct icaltimetype icaltime = icaltime_convert_to_zone (*datetime.value, to_zone);
recur_id = g_new0 (ECalComponentRange, 1);
recur_id->type = E_CAL_COMPONENT_RANGE_SINGLE;
recur_id->datetime.value = &icaltime;
recur_id->datetime.tzid = icaltimezone_get_tzid (to_zone);
e_cal_component_set_recurid (info->comp, recur_id);
g_free (recur_id); /* it's ok to call g_free here */
}
e_cal_component_free_datetime (&datetime);
e_cal_component_get_dtend (info->comp, &datetime);
info->end_time = 0;
if (datetime.value) {
struct tm end_tm;
/* If the timezone is not in the component, guess the local time */
/* Should we guess if the timezone is an olsen name somehow? */
if (datetime.value->is_utc)
from_zone = icaltimezone_get_utc_timezone ();
else if (!datetime.value->is_utc && datetime.tzid)
from_zone = icalcomponent_get_timezone (info->top_level, datetime.tzid);
else
from_zone = NULL;
if (datetime.value->is_date) {
/* RFC says the DTEND is not inclusive, thus subtract one day
* if we have a date */
icaltime_adjust (datetime.value, -1, 0, 0, 0);
}
end_tm = icaltimetype_to_tm_with_zone (datetime.value, from_zone, to_zone);
itip_view_set_end (view, &end_tm, datetime.value->is_date);
info->end_time = icaltime_as_timet_with_zone (*datetime.value, from_zone);
}
e_cal_component_free_datetime (&datetime);
/* Recurrence info */
/* FIXME Better recurring description */
if (e_cal_component_has_recurrences (info->comp)) {
/* FIXME Tell the user we don't support recurring tasks */
switch (info->type) {
case E_CAL_CLIENT_SOURCE_TYPE_EVENTS:
itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This meeting recurs"));
break;
case E_CAL_CLIENT_SOURCE_TYPE_TASKS:
itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This task recurs"));
break;
case E_CAL_CLIENT_SOURCE_TYPE_MEMOS:
itip_view_add_upper_info_item (view, ITIP_VIEW_INFO_ITEM_TYPE_INFO, _("This memo recurs"));
break;
default:
g_assert_not_reached ();
break;
}
}
if (response_enabled) {
g_signal_connect (
view, "response",
G_CALLBACK (view_response_cb), info);
itip_view_set_show_free_time_check (view, info->type == E_CAL_CLIENT_SOURCE_TYPE_EVENTS && (info->method == ICAL_METHOD_PUBLISH || info->method == ICAL_METHOD_REQUEST));
if (info->calendar_uid) {
start_calendar_server_by_uid (info, view, info->calendar_uid, info->type);
} else {
find_server (info, view, info->comp);
set_buttons_sensitive (info, view);
}
}
}