aboutsummaryrefslogtreecommitdiffstats
path: root/plugins/itip-formatter/itip-formatter.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/itip-formatter/itip-formatter.c')
-rw-r--r--plugins/itip-formatter/itip-formatter.c357
1 files changed, 249 insertions, 108 deletions
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 20fa174f60..c1571ac9cf 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -32,6 +32,7 @@
#include <camel/camel-stream.h>
#include <camel/camel-stream-mem.h>
#include <camel/camel-medium.h>
+#include <camel/camel-mime-utils.h>
#include <camel/camel-mime-message.h>
#include <camel/camel-folder.h>
#include <camel/camel-multipart.h>
@@ -91,6 +92,9 @@ typedef struct {
EAccountList *accounts;
gchar *from_address;
+ gchar *from_name;
+ gchar *to_address;
+ gchar *to_name;
gchar *delegator_address;
gchar *delegator_name;
gchar *my_address;
@@ -115,81 +119,230 @@ typedef void (* FormatItipOpenFunc) (ECal *ecal, ECalendarStatus status, gpointe
static gboolean check_is_instance (icalcomponent *icalcomp);
-static void
-find_my_address (FormatItipPObject *pitip, icalcomponent *ical_comp, icalparameter_partstat *status)
+static icalproperty *
+find_attendee (icalcomponent *ical_comp, const char *address)
{
icalproperty *prop;
- char *my_alt_address = NULL;
+
+ if (address == NULL)
+ return NULL;
+
+ for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
+ prop != NULL;
+ prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
+ const char *attendee;
+ char *text;
+
+ attendee = icalproperty_get_value_as_string (prop);
+
+ if (!attendee)
+ continue;
+
+ text = g_strdup (itip_strip_mailto (attendee));
+ text = g_strstrip (text);
+ if (text && !g_ascii_strcasecmp (address, text)) {
+ g_free (text);
+ break;
+ }
+ g_free (text);
+ }
+ return prop;
+}
+
+static icalproperty *
+find_attendee_if_sentby (icalcomponent *ical_comp, const char *address)
+{
+ icalproperty *prop;
+
+ if (address == NULL)
+ return NULL;
+
for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
prop != NULL;
prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
- icalvalue *value;
icalparameter *param;
- const char *attendee, *name;
- char *attendee_clean, *name_clean;
- EIterator *it;
-
- value = icalproperty_get_value (prop);
- if (value != NULL) {
- attendee = icalvalue_get_string (value);
- attendee_clean = g_strdup (itip_strip_mailto (attendee));
- attendee_clean = g_strstrip (attendee_clean);
- } else {
- attendee = NULL;
- attendee_clean = NULL;
- }
-
- param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
- if (param != NULL) {
- name = icalparameter_get_cn (param);
- name_clean = g_strdup (name);
- name_clean = g_strstrip (name_clean);
- } else {
- name = NULL;
- name_clean = NULL;
+ const char *attendee_sentby;
+ char *text;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
+ if (!param)
+ continue;
+
+ attendee_sentby = icalparameter_get_sentby (param);
+
+ if (!attendee_sentby)
+ continue;
+
+ text = g_strdup (itip_strip_mailto (attendee_sentby));
+ text = g_strstrip (text);
+ if (text && !g_ascii_strcasecmp (address, text)) {
+ g_free (text);
+ break;
}
+ g_free (text);
+ }
+
+ return prop;
+}
+
+static void
+find_to_address (FormatItipPObject *pitip, icalcomponent *ical_comp, icalparameter_partstat *status)
+{
+ EIterator *it;
+
+ it = e_list_get_iterator((EList *)pitip->accounts);
+
+ /* Look through the list of attendees to find the user's address */
- it = e_list_get_iterator((EList *)pitip->accounts);
+ if (!pitip->my_address)
while (e_iterator_is_valid(it)) {
const EAccount *account = e_iterator_get(it);
+ icalproperty *prop = NULL;
if (!account->enabled) {
e_iterator_next(it);
continue;
}
- /* Check for a matching address */
- if (attendee_clean != NULL
- && !g_ascii_strcasecmp (account->id->address, attendee_clean)) {
+ prop = find_attendee (ical_comp, account->id->address);
+
+ if (prop) {
+ const char *text;
+ icalparameter *param;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
+ if (param)
+ pitip->to_name = g_strdup (icalparameter_get_cn (param));
+
+ text = icalproperty_get_value_as_string (prop);
+
+ pitip->to_address = g_strdup (itip_strip_mailto (text));
+ g_strstrip (pitip->to_address);
+
pitip->my_address = g_strdup (account->id->address);
+
if (status) {
param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
*status = param ? icalparameter_get_partstat (param) : ICAL_PARTSTAT_NEEDSACTION;
}
- g_free (attendee_clean);
- g_free (name_clean);
- g_free (my_alt_address);
- g_object_unref(it);
- return;
+
+ break;
}
+ e_iterator_next(it);
+ }
+
+ e_iterator_reset (it);
+
+ /* If the user's address was not found in the attendee's list, then the user
+ * might be responding on behalf of his/her delegator. In this case, we
+ * would want to go through the SENT-BY fields of the attendees to find
+ * the user's address.
+ *
+ * Note: This functionality could have been (easily) implemented in the
+ * previous loop, but it would hurt the performance for all providers in
+ * general. Hence, we choose to iterate through the accounts list again.
+ */
+
+ if (!pitip->my_address)
+ while (e_iterator_is_valid(it)) {
+ const EAccount *account = e_iterator_get(it);
+ icalproperty *prop = NULL;
+
+ if (!account->enabled) {
+ e_iterator_next(it);
+ continue;
+ }
+
+ prop = find_attendee_if_sentby (ical_comp, account->id->address);
- /* Check for a matching cname to fall back on */
- if (name_clean != NULL
- && !g_ascii_strcasecmp (account->id->name, name_clean))
- my_alt_address = g_strdup (attendee_clean);
+ if (prop) {
+ const char *text;
+ icalparameter *param;
+ param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
+ if (param)
+ pitip->to_name = g_strdup (icalparameter_get_cn (param));
+
+ text = icalproperty_get_value_as_string (prop);
+
+ pitip->to_address = g_strdup (itip_strip_mailto (text));
+ g_strstrip (pitip->to_address);
+
+ pitip->my_address = g_strdup (account->id->address);
+
+ if (status) {
+ param = icalproperty_get_first_parameter (prop, ICAL_PARTSTAT_PARAMETER);
+ *status = param ? icalparameter_get_partstat (param) : ICAL_PARTSTAT_NEEDSACTION;
+ }
+
+ break;
+ }
e_iterator_next(it);
}
- g_object_unref(it);
- g_free (attendee_clean);
- g_free (name_clean);
+ g_object_unref(it);
+}
+
+static void
+find_from_address (FormatItipPObject *pitip, icalcomponent *ical_comp)
+{
+ EIterator *it;
+ icalproperty *prop;
+ const char *organizer;
+ icalparameter *param;
+ const char *organizer_sentby;
+ char *organizer_clean = NULL;
+ char *organizer_sentby_clean = NULL;
+
+ prop = icalcomponent_get_first_property (ical_comp, ICAL_ORGANIZER_PROPERTY);
+
+ if (!prop)
+ return;
+
+ organizer = icalproperty_get_value_as_string (prop);
+ if (organizer) {
+ organizer_clean = g_strdup (itip_strip_mailto (organizer));
+ organizer_clean = g_strstrip (organizer_clean);
}
- pitip->my_address = my_alt_address;
- if (status)
- *status = ICAL_PARTSTAT_NEEDSACTION;
+ param = icalproperty_get_first_parameter (prop, ICAL_SENTBY_PARAMETER);
+ if (param)
+ organizer_sentby = icalparameter_get_sentby (param);
+ if (organizer_sentby) {
+ organizer_sentby_clean = g_strdup (itip_strip_mailto (organizer_sentby));
+ organizer_sentby_clean = g_strstrip (organizer_sentby_clean);
+ }
+
+ if (!(organizer_sentby_clean || organizer_clean))
+ return;
+
+ pitip->from_address = g_strdup (organizer_clean);
+
+ param = icalproperty_get_first_parameter (prop, ICAL_CN_PARAMETER);
+ if (param)
+ pitip->from_name = g_strdup (icalparameter_get_cn (param));
+
+ it = e_list_get_iterator((EList *)pitip->accounts);
+ while (e_iterator_is_valid(it)) {
+ const EAccount *account = e_iterator_get(it);
+
+ if (!account->enabled) {
+ e_iterator_next(it);
+ continue;
+ }
+
+ if ((organizer_clean && !g_ascii_strcasecmp (organizer_clean, account->id->address))
+ || (organizer_sentby_clean && !g_ascii_strcasecmp (organizer_sentby_clean, account->id->address))) {
+ pitip->my_address = g_strdup (account->id->address);
+
+ break;
+ }
+ e_iterator_next(it);
+ }
+ g_object_unref(it);
+ g_free (organizer_sentby_clean);
+ g_free (organizer_clean);
}
static ECalComponent *
@@ -657,39 +810,6 @@ cleanup_ecal (gpointer data)
g_object_unref (ecal);
}
-static icalproperty *
-find_attendee (icalcomponent *ical_comp, const char *address)
-{
- icalproperty *prop;
-
- if (address == NULL)
- return NULL;
-
- for (prop = icalcomponent_get_first_property (ical_comp, ICAL_ATTENDEE_PROPERTY);
- prop != NULL;
- prop = icalcomponent_get_next_property (ical_comp, ICAL_ATTENDEE_PROPERTY)) {
- icalvalue *value;
- const char *attendee;
- char *text;
-
- value = icalproperty_get_value (prop);
- if (!value)
- continue;
-
- attendee = icalvalue_get_string (value);
-
- text = g_strdup (itip_strip_mailto (attendee));
- text = g_strstrip (text);
- if (!g_ascii_strcasecmp (address, text)) {
- g_free (text);
- break;
- }
- g_free (text);
- }
-
- return prop;
-}
-
static gboolean
change_status (icalcomponent *ical_comp, const char *address, icalparameter_partstat status)
{
@@ -1305,25 +1425,28 @@ extract_itip_data (FormatItipPObject *pitip, GtkContainer *container)
}
if (icalcomponent_isa (pitip->ical_comp) != ICAL_VJOURNAL_COMPONENT) {
+ 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 (comp, NULL);
g_object_unref (comp);
comp = NULL;
- prop = find_attendee (pitip->ical_comp, my_address);
-
+ 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 char * delfrom;
- if ((param =icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER))) {
+ if ((param = icalproperty_get_first_parameter (prop, ICAL_DELEGATEDFROM_PARAMETER))) {
delfrom = icalparameter_get_delegatedfrom (param);
pitip->delegator_address = g_strdup (itip_strip_mailto (delfrom));
}
-
}
+ prop = NULL;
/* Determine any delegate sections */
prop = icalcomponent_get_first_property (pitip->ical_comp, ICAL_X_PROPERTY);
@@ -1405,7 +1528,8 @@ extract_itip_data (FormatItipPObject *pitip, GtkContainer *container)
e_cal_component_alarm_free (acomp);
}
- find_my_address (pitip, pitip->ical_comp, NULL);
+ find_from_address (pitip, pitip->ical_comp);
+ find_to_address (pitip, pitip->ical_comp, NULL);
return TRUE;
}
@@ -1441,8 +1565,8 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
e_cal_component_set_transparency (pitip->comp, E_CAL_COMPONENT_TRANSP_OPAQUE);
- if (!pitip->my_address && pitip->current_ecal != NULL)
- e_cal_get_cal_address (pitip->current_ecal, &pitip->my_address, NULL);
+ if (!pitip->to_address && pitip->current_ecal != NULL)
+ e_cal_get_cal_address (pitip->current_ecal, &pitip->to_address, NULL);
/* check if it is a recur instance (no master object) and
* add a property */
@@ -1455,7 +1579,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
switch (response) {
case ITIP_VIEW_RESPONSE_ACCEPT:
if (pitip->type != E_CAL_SOURCE_TYPE_JOURNAL)
- status = change_status (pitip->ical_comp, pitip->my_address,
+ status = change_status (pitip->ical_comp, pitip->to_address,
ICAL_PARTSTAT_ACCEPTED);
else
status = TRUE;
@@ -1467,7 +1591,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
}
break;
case ITIP_VIEW_RESPONSE_TENTATIVE:
- status = change_status (pitip->ical_comp, pitip->my_address,
+ status = change_status (pitip->ical_comp, pitip->to_address,
ICAL_PARTSTAT_TENTATIVE);
if (status) {
e_cal_component_rescan (pitip->comp);
@@ -1479,7 +1603,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
break;
case ITIP_VIEW_RESPONSE_DECLINE:
if (pitip->type != E_CAL_SOURCE_TYPE_JOURNAL)
- status = change_status (pitip->ical_comp, pitip->my_address,
+ status = change_status (pitip->ical_comp, pitip->to_address,
ICAL_PARTSTAT_DECLINED);
else {
prop = icalproperty_new_x ("1");
@@ -1569,9 +1693,9 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
if (comp == NULL)
return;
- if (pitip->my_address == NULL)
- find_my_address (pitip, pitip->ical_comp, NULL);
- g_assert (pitip->my_address != NULL);
+ if (pitip->to_address == NULL)
+ find_to_address (pitip, pitip->ical_comp, NULL);
+ g_assert (pitip->to_address != NULL);
ical_comp = e_cal_component_get_icalcomponent (comp);
@@ -1594,9 +1718,9 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
/* We do this to ensure there is at most one
* attendee in the response */
- if (found || g_ascii_strcasecmp (pitip->my_address, text))
- list = g_slist_prepend (list, prop);
- else if (!g_ascii_strcasecmp (pitip->my_address, text))
+ if (found || g_ascii_strcasecmp (pitip->to_address, text))
+ list = g_slist_prepend (list, prop);
+ else if (!g_ascii_strcasecmp (pitip->to_address, text))
found = TRUE;
g_free (text);
}
@@ -1625,8 +1749,7 @@ view_response_cb (GtkWidget *widget, ItipViewResponse response, gpointer data)
e_cal_component_rescan (comp);
if (itip_send_comp (E_CAL_COMPONENT_METHOD_REPLY, comp, pitip->current_ecal, pitip->top_level, NULL, NULL)) {
- camel_folder_set_message_flags (((EMFormat *) pitip->pobject.format)->folder, ((EMFormat *) pitip->pobject.format)->uid,
- CAMEL_MESSAGE_ANSWERED, CAMEL_MESSAGE_ANSWERED);
+ camel_folder_set_message_flags (((EMFormat *) pitip->pobject.format)->folder, ((EMFormat *) pitip->pobject.format)->uid, CAMEL_MESSAGE_ANSWERED, CAMEL_MESSAGE_ANSWERED);
}
g_object_unref (comp);
@@ -1729,7 +1852,7 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
switch (pitip->method) {
case ICAL_METHOD_REQUEST:
/* FIXME What about the name? */
- itip_view_set_delegator (ITIP_VIEW (pitip->view), pitip->delegator_address);
+ itip_view_set_delegator (ITIP_VIEW (pitip->view), pitip->delegator_name ? pitip->delegator_name : pitip->delegator_address);
case ICAL_METHOD_PUBLISH:
case ICAL_METHOD_ADD:
case ICAL_METHOD_CANCEL:
@@ -1739,15 +1862,17 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
/* An organizer sent this */
e_cal_component_get_organizer (pitip->comp, &organizer);
org = organizer.cn ? organizer.cn : itip_strip_mailto (organizer.value);
+
itip_view_set_organizer (ITIP_VIEW (pitip->view), org);
- /* FIXME, do i need to strip the sentby somehow? Maybe with camel? */
- itip_view_set_sentby (ITIP_VIEW (pitip->view), organizer.sentby);
-
- /* FIXME try and match sender with organizer/attendee/sentby?
- pd->from_address = camel_address_encode
- ((CamelAddress *)from); g_message ("Detected from address %s",
- pd->from_address);
- */
+ if (organizer.sentby)
+ itip_view_set_organizer_sentby (ITIP_VIEW (pitip->view), itip_strip_mailto (organizer.sentby));
+
+ if (pitip->my_address) {
+ if !(organizer.value && !g_ascii_strcasecmp (itip_strip_mailto (organizer.value), pitip->my_address))
+ && !(organizer.sentby && !g_ascii_strcasecmp (itip_strip_mailto (organizer.sentby), pitip->my_address))
+ && (pitip->to_address && g_ascii_strcasecmp (pitip->to_address, pitip->my_address))
+ itip_view_set_proxy (ITIP_VIEW (pitip->view), pitip->to_name ? pitip->to_name : pitip->to_address);
+ }
break;
case ICAL_METHOD_REPLY:
case ICAL_METHOD_REFRESH:
@@ -1760,9 +1885,19 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
ECalComponentAttendee *attendee;
attendee = list->data;
-
+
itip_view_set_attendee (ITIP_VIEW (pitip->view), attendee->cn ? attendee->cn : itip_strip_mailto (attendee->value));
+ if (attendee->sentby)
+ itip_view_set_attendee_sentby (ITIP_VIEW (pitip->view), itip_strip_mailto (attendee->sentby));
+
+ if (pitip->my_address) {
+ if !(attendee->value && !g_ascii_strcasecmp (itip_strip_mailto (attendee->value), pitip->my_address))
+ && !(attendee->sentby && !g_ascii_strcasecmp (itip_strip_mailto (attendee->sentby), pitip->my_address))
+ && (pitip->from_address && g_ascii_strcasecmp (pitip->from_address, pitip->my_address))
+ itip_view_set_proxy (ITIP_VIEW (pitip->view), pitip->from_name ? pitip->from_name : pitip->from_address);
+ }
+
e_cal_component_free_attendee_list (list);
}
break;
@@ -1807,7 +1942,7 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
|| pitip->method == ICAL_METHOD_COUNTER
|| pitip->method == ICAL_METHOD_DECLINECOUNTER) {
/* FIXME Check spec to see if multiple comments are actually valid */
- /* Comments for ITIP are limited to one per object */
+ /* Comments for iTIP are limited to one per object */
e_cal_component_get_comment_list (pitip->comp, &list);
if (list) {
ECalComponentText *text = list->data;
@@ -1921,7 +2056,7 @@ format_itip_object (EMFormatHTML *efh, GtkHTMLEmbedded *eb, EMFormatHTMLPObject
find_server (pitip, pitip->comp);
set_buttons_sensitive (pitip);
}
-
+
return TRUE;
}
@@ -1964,6 +2099,12 @@ pitip_free (EMFormatHTMLPObject *pobject)
g_free (pitip->from_address);
pitip->from_address = NULL;
+ g_free (pitip->from_name);
+ pitip->from_name = NULL;
+ g_free (pitip->to_address);
+ pitip->to_address = NULL;
+ g_free (pitip->to_name);
+ pitip->to_name = NULL;
g_free (pitip->delegator_address);
pitip->delegator_address = NULL;
g_free (pitip->delegator_name);