[evolution-ews] Bug 654459 - Support recurrence task
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug 654459 - Support recurrence task
- Date: Wed, 21 Mar 2018 10:19:27 +0000 (UTC)
commit dd753a52ad2e376470bd39c041a209c3f7530ac0
Author: Milan Crha <mcrha redhat com>
Date: Wed Mar 21 11:17:50 2018 +0100
Bug 654459 - Support recurrence task
po/POTFILES.in | 1 +
src/addressbook/e-book-backend-ews.c | 28 +-
src/calendar/e-cal-backend-ews-utils.c | 112 ++-
src/calendar/e-cal-backend-ews-utils.h | 10 +-
src/calendar/e-cal-backend-ews.c | 4 +
src/camel/camel-ews-folder.c | 14 +-
src/camel/camel-ews-store.c | 7 +-
src/server/e-ews-calendar-utils.c | 1474 +++++++++++++++++++++++++++++++-
src/server/e-ews-calendar-utils.h | 17 +-
src/server/e-ews-camel-common.c | 7 +-
src/server/e-ews-connection.c | 69 ++-
src/server/e-ews-connection.h | 5 +-
src/server/e-ews-item.c | 568 ++++++++++++-
src/server/e-ews-item.h | 89 ++
tests/ews-test-timezones.c | 2 +-
15 files changed, 2290 insertions(+), 117 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a6a06da..6fc898a 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -26,6 +26,7 @@ src/configuration/e-mail-config-ews-gal.c
src/configuration/e-mail-config-ews-ooo-page.c
src/configuration/module-ews-configuration.error.xml
src/server/camel-sasl-xoauth2-office365.c
+src/server/e-ews-calendar-utils.c
src/server/e-ews-camel-common.c
src/server/e-ews-connection.c
src/server/e-ews-connection-utils.c
diff --git a/src/addressbook/e-book-backend-ews.c b/src/addressbook/e-book-backend-ews.c
index 79d6f34..65c1870 100644
--- a/src/addressbook/e-book-backend-ews.c
+++ b/src/addressbook/e-book-backend-ews.c
@@ -1343,9 +1343,10 @@ ebb_ews_write_dl_members (ESoapMessage *msg,
e_soap_message_end_element (msg); /* Members */
}
-static void
+static gboolean
ebb_ews_convert_dl_to_xml_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EContact *contact = user_data;
EVCardAttribute *attribute;
@@ -1361,11 +1362,14 @@ ebb_ews_convert_dl_to_xml_cb (ESoapMessage *msg,
ebb_ews_write_dl_members (msg, contact);
e_soap_message_end_element (msg); /* DistributionList */
+
+ return TRUE;
}
-static void
+static gboolean
ebb_ews_convert_contact_to_xml_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EContact *contact = user_data;
gint i, element_type;
@@ -1393,6 +1397,8 @@ ebb_ews_convert_contact_to_xml_cb (ESoapMessage *msg,
/* end of "Contact" */
e_soap_message_end_element (msg);
+
+ return TRUE;
}
typedef struct _ConvertData {
@@ -1405,9 +1411,10 @@ typedef struct _ConvertData {
gchar *change_key;
} ConvertData;
-static void
+static gboolean
ebb_ews_convert_dl_to_updatexml_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
ConvertData *cd = user_data;
EContact *old_contact = cd->old_contact;
@@ -1421,11 +1428,14 @@ ebb_ews_convert_dl_to_updatexml_cb (ESoapMessage *msg,
ebb_ews_write_dl_members (msg, new_contact);
e_ews_message_end_set_item_field (msg);
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
-static void
+static gboolean
ebb_ews_convert_contact_to_updatexml_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
ConvertData *cd = user_data;
EContact *old_contact = cd->old_contact;
@@ -1486,6 +1496,8 @@ ebb_ews_convert_contact_to_updatexml_cb (ESoapMessage *msg,
}
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
static EContact *
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index eec1544..738af3f 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -1059,9 +1059,10 @@ check_is_all_day_event (const struct icaltimetype dtstart,
return ((secs_end - secs_start) % (24 * 60 * 60)) == 0 && (secs_start % 24 * 60 * 60) == 0;
}
-static void
+static gboolean
convert_vevent_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = convert_data->icalcomp;
@@ -1213,11 +1214,14 @@ convert_vevent_calcomp_to_xml (ESoapMessage *msg,
e_soap_message_end_element (msg); /* "CalendarItem" */
g_object_unref (comp);
+
+ return TRUE;
}
-static void
+static gboolean
convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = convert_data->icalcomp;
@@ -1225,6 +1229,7 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
icaltimetype dt;
gint value;
gchar buffer[16];
+ gboolean success;
/* gboolean has_alarms; */
e_soap_message_start_element (msg, "Task", NULL, NULL);
@@ -1250,6 +1255,8 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
}
+ success = e_ews_cal_utils_set_recurrence (msg, icalcomp, FALSE, error);
+
prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
if (prop) {
dt = icalproperty_get_dtstart (prop);
@@ -1287,11 +1294,14 @@ convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");*/
e_soap_message_end_element (msg); /* "Task" */
+
+ return success;
}
-static void
+static gboolean
convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = convert_data->icalcomp;
@@ -1312,28 +1322,34 @@ convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
e_soap_message_end_element (msg); /* Message */
+
+ return TRUE;
}
-void
+gboolean
e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
+ gboolean success = FALSE;
switch (icalcomponent_isa (convert_data->icalcomp)) {
case ICAL_VEVENT_COMPONENT:
- convert_vevent_calcomp_to_xml (msg, convert_data);
+ success = convert_vevent_calcomp_to_xml (msg, convert_data, error);
break;
case ICAL_VTODO_COMPONENT:
- convert_vtodo_calcomp_to_xml (msg, convert_data);
+ success = convert_vtodo_calcomp_to_xml (msg, convert_data, error);
break;
case ICAL_VJOURNAL_COMPONENT:
- convert_vjournal_calcomp_to_xml (msg, convert_data);
+ success = convert_vjournal_calcomp_to_xml (msg, convert_data, error);
break;
default:
g_warn_if_reached ();
break;
}
+
+ return success;
}
static void
@@ -1393,9 +1409,10 @@ convert_vevent_property_to_updatexml (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
}
-static void
+static gboolean
convert_vevent_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
@@ -1415,7 +1432,6 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
gboolean satisfies;
gint alarm = 0, alarm_old = 0;
gchar *recid;
- GError *error = NULL;
/* Modifying a recurring meeting ? */
if (icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY) != NULL) {
@@ -1432,7 +1448,7 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
convert_data->default_zone,
recid,
icalcomp_old,
- &error));
+ NULL));
g_free (recid);
} else {
e_ews_message_start_item_change (
@@ -1515,8 +1531,9 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
org_email_address = e_ews_collect_organizer (icalcomp);
if (org_email_address && convert_data->user_email && g_ascii_strcasecmp (org_email_address,
convert_data->user_email)) {
e_ews_message_end_item_change (msg);
- return;
+ return TRUE;
}
+
/* Update other properties allowed only for meeting organizers*/
/*meeting dates*/
dtstart = icalcomponent_get_dtstart (icalcomp);
@@ -1697,6 +1714,8 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
}
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
static void
@@ -1712,9 +1731,10 @@ convert_vtodo_property_to_updatexml (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
}
-static void
+static gboolean
convert_vtodo_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
@@ -1722,6 +1742,7 @@ convert_vtodo_component_to_updatexml (ESoapMessage *msg,
icaltimetype dt;
gint value;
gchar buffer[16];
+ gboolean success = TRUE;
e_ews_message_start_item_change (
msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
@@ -1762,6 +1783,17 @@ convert_vtodo_component_to_updatexml (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
}
+ /* Recurrence */
+ value = icalcomponent_count_properties (e_cal_component_get_icalcomponent (convert_data->old_comp),
ICAL_RRULE_PROPERTY);
+ if (icalcomponent_count_properties (icalcomp, ICAL_RRULE_PROPERTY) > 0 ||
+ (e_cal_util_find_x_property (icalcomp, X_EWS_TASK_REGENERATION) && value <= 0)) {
+ e_ews_message_start_set_item_field (msg, "Recurrence", "task", "Task");
+ success = success && e_ews_cal_utils_set_recurrence (msg, icalcomp, FALSE, error);
+ e_ews_message_end_set_item_field (msg); /* Recurrence */
+ } else if (value > 0) {
+ e_ews_message_add_delete_item_field (msg, "Recurrence", "task");
+ }
+
prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
if (prop) {
dt = icalproperty_get_dtstart (prop);
@@ -1794,6 +1826,8 @@ convert_vtodo_component_to_updatexml (ESoapMessage *msg,
convert_component_categories_to_updatexml (convert_data->comp, msg, "Task");
e_ews_message_end_item_change (msg);
+
+ return success;
}
static void
@@ -1809,9 +1843,10 @@ convert_vjournal_property_to_updatexml (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
}
-static void
+static gboolean
convert_vjournal_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
@@ -1847,28 +1882,34 @@ convert_vjournal_component_to_updatexml (ESoapMessage *msg,
convert_component_categories_to_updatexml (convert_data->comp, msg, "Message");
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
-void
+gboolean
e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+ gboolean success = FALSE;
switch (icalcomponent_isa (icalcomp)) {
case ICAL_VEVENT_COMPONENT:
- convert_vevent_component_to_updatexml (msg, user_data);
+ success = convert_vevent_component_to_updatexml (msg, user_data, error);
break;
case ICAL_VTODO_COMPONENT:
- convert_vtodo_component_to_updatexml (msg, user_data);
+ success = convert_vtodo_component_to_updatexml (msg, user_data, error);
break;
case ICAL_VJOURNAL_COMPONENT:
- convert_vjournal_component_to_updatexml (msg, user_data);
+ success = convert_vjournal_component_to_updatexml (msg, user_data, error);
break;
default:
break;
}
+
+ return success;
}
guint
@@ -1910,9 +1951,10 @@ e_cal_backend_ews_rid_to_index (icaltimezone *timezone,
return index;
}
-void
+gboolean
e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *convert_data = user_data;
@@ -1930,11 +1972,14 @@ e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
-void
+gboolean
e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *data = user_data;
@@ -1947,11 +1992,14 @@ e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,
e_ews_message_end_set_item_field (msg);
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
-void
+gboolean
e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
EwsCalendarConvertData *data = user_data;
const gchar *response_type = data->response_type;
@@ -1976,4 +2024,6 @@ e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg,
/* end of "AcceptItem" */
e_soap_message_end_element (msg);
+
+ return TRUE;
}
diff --git a/src/calendar/e-cal-backend-ews-utils.h b/src/calendar/e-cal-backend-ews-utils.h
index 4aea6d2..32493f6 100644
--- a/src/calendar/e-cal-backend-ews-utils.h
+++ b/src/calendar/e-cal-backend-ews-utils.h
@@ -71,11 +71,11 @@ const gchar *e_cal_backend_ews_tz_util_get_ical_equivalent (const gchar *msdn_tz
void e_cal_backend_ews_populate_windows_zones (void);
void e_cal_backend_ews_unref_windows_zones (void);
-void e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg, gpointer user_data);
-void e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg, gpointer user_data);
-void e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg, gpointer user_data);
-void e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,gpointer user_data);
-void e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg, gpointer user_data);
+gboolean e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg, gpointer user_data, GError **error);
+gboolean e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg, gpointer user_data, GError
**error);
+gboolean e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg, gpointer user_data, GError **error);
+gboolean e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,gpointer user_data, GError
**error);
+gboolean e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg, gpointer user_data, GError
**error);
guint e_cal_backend_ews_rid_to_index (icaltimezone *timezone, const gchar *rid, icalcomponent *comp, GError
**error);
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 447732e..1d48492 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -477,6 +477,9 @@ ecb_ews_item_to_component_sync (ECalBackendEws *cbews,
icalprop = icalproperty_new_priority (priority);
icalcomponent_add_property (icalcomp, icalprop);
+ /* recurrence */
+ e_ews_cal_utils_recurrence_to_rrule (item, icalcomp);
+
/* reminders */
/* The Exchange server stores start of the Task reminder and Start of the Task
itself in separate properties, which doesn't work for evolution at the moment. */
@@ -3702,6 +3705,7 @@ ecb_ews_get_backend_property (ECalBackend *cal_backend,
CAL_STATIC_CAPABILITY_ALL_DAY_EVENT_AS_TIME,
CAL_STATIC_CAPABILITY_TASK_DATE_ONLY,
CAL_STATIC_CAPABILITY_TASK_NO_ALARM,
+ CAL_STATIC_CAPABILITY_TASK_CAN_RECUR,
e_cal_meta_backend_get_capabilities (E_CAL_META_BACKEND (cbews)),
NULL);
} else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS)) {
diff --git a/src/camel/camel-ews-folder.c b/src/camel/camel-ews-folder.c
index e3157c5..cc1c266 100644
--- a/src/camel/camel-ews-folder.c
+++ b/src/camel/camel-ews-folder.c
@@ -991,9 +991,10 @@ ews_folder_search_free (CamelFolder *folder,
/********************* folder functions*************************/
-static void
+static gboolean
msg_update_flags (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
/* the mi_list is owned by the caller */
const GSList *mi_list = user_data, *iter;
@@ -1111,11 +1112,14 @@ msg_update_flags (ESoapMessage *msg,
camel_folder_summary_unlock (summary);
g_clear_object (&summary);
}
+
+ return TRUE;
}
-static void
+static gboolean
ews_suppress_read_receipt (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
/* the mi_list is owned by the caller */
const GSList *mi_list = user_data, *iter;
@@ -1154,6 +1158,8 @@ ews_suppress_read_receipt (ESoapMessage *msg,
camel_folder_summary_unlock (summary);
g_clear_object (&summary);
}
+
+ return TRUE;
}
static gboolean
diff --git a/src/camel/camel-ews-store.c b/src/camel/camel-ews-store.c
index d309277..5974754 100644
--- a/src/camel/camel-ews-store.c
+++ b/src/camel/camel-ews-store.c
@@ -2817,9 +2817,10 @@ struct _rename_cb_data {
const gchar *folder_id;
};
-static void
+static gboolean
rename_folder_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
struct _rename_cb_data *rename_data = user_data;
@@ -2838,6 +2839,8 @@ rename_folder_cb (ESoapMessage *msg,
e_soap_message_end_element (msg); /* SetFolderField */
e_ews_message_end_item_change (msg);
+
+ return TRUE;
}
static gboolean
diff --git a/src/server/e-ews-calendar-utils.c b/src/server/e-ews-calendar-utils.c
index 6e84350..406e87c 100644
--- a/src/server/e-ews-calendar-utils.c
+++ b/src/server/e-ews-calendar-utils.c
@@ -19,10 +19,184 @@
#include "evolution-ews-config.h"
+#include <glib/gi18n-lib.h>
+#include <libecal/libecal.h>
+
#include "e-ews-message.h"
+#include "ews-errors.h"
#include "e-ews-calendar-utils.h"
+static void
+e_ews_cal_util_encode_regeneration (EEwsRecurrence *in_recur,
+ icalcomponent *out_comp) /* not 'out' as such */
+{
+ gchar chr = 0;
+
+ g_return_if_fail (in_recur != NULL);
+ g_return_if_fail (out_comp != NULL);
+
+ switch (in_recur->type) {
+ case E_EWS_RECURRENCE_DAILY_REGENERATION:
+ chr = 'D';
+ break;
+ case E_EWS_RECURRENCE_WEEKLY_REGENERATION:
+ chr = 'W';
+ break;
+ case E_EWS_RECURRENCE_MONTHLY_REGENERATION:
+ chr = 'M';
+ break;
+ case E_EWS_RECURRENCE_YEARLY_REGENERATION:
+ chr = 'Y';
+ break;
+ default:
+ break;
+ }
+
+ if (chr && in_recur->end_type != E_EWS_RECURRENCE_END_UNKNOWN) {
+ gchar end_chr = 0;
+ gint64 end_num = 0;
+
+ switch (in_recur->end_type) {
+ case E_EWS_RECURRENCE_END_UNKNOWN:
+ g_warn_if_reached ();
+ break;
+ case E_EWS_RECURRENCE_END_NO_END:
+ end_chr = 'X';
+ end_num = 0;
+ break;
+ case E_EWS_RECURRENCE_END_DATE:
+ end_chr = 'D';
+ end_num = (gint64) in_recur->end.utc_end_date;
+ break;
+ case E_EWS_RECURRENCE_END_NUMBERED:
+ end_chr = 'N';
+ end_num = (gint64) in_recur->end.number_of_occurrences;
+ break;
+ }
+
+ if (end_chr) {
+ gchar *value;
+ gint64 start_num;
+
+ start_num = (gint64) in_recur->utc_start_date;
+
+ value = g_strdup_printf ("%c.%d.%c.%" G_GINT64_FORMAT ".%" G_GINT64_FORMAT,
+ chr,
+ in_recur->recur.interval,
+ end_chr,
+ start_num,
+ end_num);
+ e_cal_util_set_x_property (out_comp, X_EWS_TASK_REGENERATION, value);
+ g_free (value);
+ }
+ } else {
+ e_cal_util_remove_x_property (out_comp, X_EWS_TASK_REGENERATION);
+ }
+}
+
+static gboolean
+e_ews_cal_util_decode_regeneration_info_from_string (const gchar *value,
+ gchar *out_recur_type_chr,
+ gint *out_interval,
+ gchar *out_end_type_chr,
+ gint64 *out_start_num,
+ gint64 *out_end_num)
+{
+ gchar **parts;
+
+ if (!value || !*value)
+ return FALSE;
+
+ parts = g_strsplit (value, ".", -1);
+
+ if (g_strv_length (parts) != 5) {
+ g_strfreev (parts);
+ return FALSE;
+ }
+
+ if (out_recur_type_chr)
+ *out_recur_type_chr = parts[0][0];
+
+ if (out_interval)
+ *out_interval = (gint) g_ascii_strtoll (parts[1], NULL, 10);
+
+ if (out_end_type_chr)
+ *out_end_type_chr = parts[2][0];
+
+ if (out_start_num)
+ *out_start_num = g_ascii_strtoll (parts[3], NULL, 10);
+
+ if (out_end_num)
+ *out_end_num = g_ascii_strtoll (parts[4], NULL, 10);
+
+ g_strfreev (parts);
+
+ return TRUE;
+}
+
+static void
+e_ews_cal_util_decode_regeneration (icalcomponent *in_comp,
+ EEwsRecurrence *out_recur)
+{
+ const gchar *value;
+ gchar recur_type_chr = 0, end_type_chr = 0;
+ gint interval = 0;
+ gint64 start_num = 0, end_num = 0;
+
+ g_return_if_fail (in_comp != NULL);
+ g_return_if_fail (out_recur != NULL);
+
+ value = e_cal_util_get_x_property (in_comp, X_EWS_TASK_REGENERATION);
+
+ if (e_ews_cal_util_decode_regeneration_info_from_string (value, &recur_type_chr, &interval,
&end_type_chr, &start_num, &end_num)) {
+ EEwsRecurrenceType recur_type = E_EWS_RECURRENCE_UNKNOWN;
+ EEwsRecurrenceEndType end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+
+ switch (recur_type_chr) {
+ case 'D':
+ recur_type = E_EWS_RECURRENCE_DAILY_REGENERATION;
+ break;
+ case 'W':
+ recur_type = E_EWS_RECURRENCE_WEEKLY_REGENERATION;
+ break;
+ case 'M':
+ recur_type = E_EWS_RECURRENCE_MONTHLY_REGENERATION;
+ break;
+ case 'Y':
+ recur_type = E_EWS_RECURRENCE_YEARLY_REGENERATION;
+ break;
+ }
+
+ switch (end_type_chr) {
+ case 'X':
+ end_type = E_EWS_RECURRENCE_END_NO_END;
+ break;
+ case 'D':
+ end_type = E_EWS_RECURRENCE_END_DATE;
+ break;
+ case 'N':
+ end_type = E_EWS_RECURRENCE_END_NUMBERED;
+ break;
+ }
+
+ if (recur_type != E_EWS_RECURRENCE_UNKNOWN && end_type != E_EWS_RECURRENCE_END_UNKNOWN &&
+ start_num > 0 && (end_type == E_EWS_RECURRENCE_END_NO_END || end_num > 0) && interval >
0) {
+ out_recur->type = recur_type;
+ out_recur->recur.interval = interval;
+ out_recur->end_type = end_type;
+ out_recur->utc_start_date = (time_t) start_num;
+
+ if (end_type == E_EWS_RECURRENCE_END_DATE)
+ out_recur->end.utc_end_date = (time_t) end_num;
+ else if (end_type == E_EWS_RECURRENCE_END_NUMBERED)
+ out_recur->end.number_of_occurrences = (gint) end_num;
+ }
+ } else if (value && *value) {
+ g_warning ("%s: Failed to decode value '%s'", G_STRFUNC, value);
+ }
+}
+
static const gchar *
number_to_weekday (gint num)
{
@@ -165,16 +339,17 @@ ewscal_set_availability_timezone (ESoapMessage *msg,
e_soap_message_end_element (msg); /* "TimeZone" */
}
-void
+gboolean
e_ews_cal_utils_prepare_free_busy_request (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
const EEWSFreeBusyData *fbdata = user_data;
icaltimetype t_start, t_end;
icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
GSList *link;
- g_return_if_fail (fbdata != NULL);
+ g_return_val_if_fail (fbdata != NULL, FALSE);
ewscal_set_availability_timezone (msg, utc_zone);
@@ -210,6 +385,8 @@ e_ews_cal_utils_prepare_free_busy_request (ESoapMessage *msg,
e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
+
+ return TRUE;
}
void
@@ -256,3 +433,1294 @@ e_ews_cal_utils_set_time (ESoapMessage *msg,
g_free (tz_ident);
g_free (str);
}
+
+static gint
+e_ews_cal_util_recurrence_count_by_xxx (gshort *field,
+ gint max_elements)
+{
+ gint ii;
+
+ for (ii = 0; ii < max_elements; ii++)
+ if (field[ii] == ICAL_RECURRENCE_ARRAY_MAX)
+ break;
+
+ return ii;
+}
+
+static EEwsRecurrenceDaysOfWeek
+e_ews_cal_util_month_index_to_days_of_week (gint month_index)
+{
+ switch (month_index) {
+ case 0:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ case 1:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ case 2:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ case 3:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ case 4:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ case 5:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ case 6:
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ default:
+ g_warning ("%s: What is month_index:%d for the last day?", G_STRFUNC, month_index);
+ break;
+ }
+
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+}
+
+enum month_num_options {
+ MONTH_NUM_INVALID = -1,
+ MONTH_NUM_FIRST,
+ MONTH_NUM_SECOND,
+ MONTH_NUM_THIRD,
+ MONTH_NUM_FOURTH,
+ MONTH_NUM_FIFTH,
+ MONTH_NUM_LAST,
+ MONTH_NUM_DAY,
+ MONTH_NUM_OTHER
+};
+
+enum month_day_options {
+ MONTH_DAY_NTH,
+ MONTH_DAY_MON,
+ MONTH_DAY_TUE,
+ MONTH_DAY_WED,
+ MONTH_DAY_THU,
+ MONTH_DAY_FRI,
+ MONTH_DAY_SAT,
+ MONTH_DAY_SUN
+};
+
+static EEwsRecurrenceDayOfWeekIndex
+e_ews_cal_util_month_num_to_day_of_week_index (gint month_num)
+{
+ switch (month_num) {
+ case MONTH_NUM_FIRST:
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FIRST;
+ case MONTH_NUM_SECOND:
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_SECOND;
+ case MONTH_NUM_THIRD:
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_THIRD;
+ case MONTH_NUM_FOURTH:
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FOURTH;
+ case MONTH_NUM_FIFTH:
+ case MONTH_NUM_LAST:
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST;
+ default:
+ break;
+ }
+
+ return E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+}
+
+static gboolean
+e_ews_cal_utils_convert_recurrence (icalcomponent *icalcomp,
+ EEwsRecurrence *out_recur,
+ GError **error)
+{
+ icalproperty *prop;
+ struct icalrecurrencetype rrule;
+ gint n_by_second, n_by_minute, n_by_hour;
+ gint n_by_day, n_by_month_day, n_by_year_day;
+ gint n_by_week_no, n_by_month, n_by_set_pos;
+
+ g_return_val_if_fail (icalcomp != NULL, FALSE);
+ g_return_val_if_fail (out_recur != NULL, FALSE);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+ if (!prop) {
+ e_ews_cal_util_decode_regeneration (icalcomp, out_recur);
+ return TRUE;
+ }
+
+ switch (icalcomponent_isa (icalcomp)) {
+ case ICAL_VEVENT_COMPONENT:
+ case ICAL_VTODO_COMPONENT:
+ case ICAL_VJOURNAL_COMPONENT:
+ break;
+ default:
+ return TRUE;
+ }
+
+ out_recur->type = E_EWS_RECURRENCE_UNKNOWN;
+ out_recur->end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+
+ if (icalcomponent_count_properties (icalcomp, ICAL_RRULE_PROPERTY) != 1 ||
+ icalcomponent_count_properties (icalcomp, ICAL_RDATE_PROPERTY) != 0 ||
+ icalcomponent_count_properties (icalcomp, ICAL_EXRULE_PROPERTY) != 0)
+ goto custom;
+
+ rrule = icalproperty_get_rrule (prop);
+
+ switch (rrule.freq) {
+ case ICAL_DAILY_RECURRENCE:
+ case ICAL_WEEKLY_RECURRENCE:
+ case ICAL_MONTHLY_RECURRENCE:
+ case ICAL_YEARLY_RECURRENCE:
+ break;
+ default:
+ goto custom;
+
+ }
+
+#define N_HAS_BY(field) (e_ews_cal_util_recurrence_count_by_xxx (field, G_N_ELEMENTS (field)))
+
+ n_by_second = N_HAS_BY (rrule.by_second);
+ n_by_minute = N_HAS_BY (rrule.by_minute);
+ n_by_hour = N_HAS_BY (rrule.by_hour);
+ n_by_day = N_HAS_BY (rrule.by_day);
+ n_by_month_day = N_HAS_BY (rrule.by_month_day);
+ n_by_year_day = N_HAS_BY (rrule.by_year_day);
+ n_by_week_no = N_HAS_BY (rrule.by_week_no);
+ n_by_month = N_HAS_BY (rrule.by_month);
+ n_by_set_pos = N_HAS_BY (rrule.by_set_pos);
+
+#undef N_HAS_BY
+
+ if (n_by_second != 0 ||
+ n_by_minute != 0 ||
+ n_by_hour != 0)
+ goto custom;
+
+ switch (rrule.freq) {
+ case ICAL_DAILY_RECURRENCE:
+ if (n_by_day != 0 ||
+ n_by_month_day != 0 ||
+ n_by_year_day != 0 ||
+ n_by_week_no != 0 ||
+ n_by_month != 0 ||
+ n_by_set_pos != 0)
+ goto custom;
+
+ if (rrule.interval > 0) {
+ out_recur->type = E_EWS_RECURRENCE_DAILY;
+ out_recur->recur.interval = rrule.interval;
+ }
+ break;
+
+ case ICAL_WEEKLY_RECURRENCE: {
+ gint ii, ndays;
+ guint8 day_mask;
+
+ if (n_by_month_day != 0 ||
+ n_by_year_day != 0 ||
+ n_by_week_no != 0 ||
+ n_by_month != 0 ||
+ n_by_set_pos != 0)
+ goto custom;
+
+ day_mask = 0;
+
+ for (ii = 0; ii < 8 && rrule.by_day[ii] != ICAL_RECURRENCE_ARRAY_MAX; ii++) {
+ enum icalrecurrencetype_weekday weekday;
+ gint pos;
+
+ weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[ii]);
+ pos = icalrecurrencetype_day_position (rrule.by_day[ii]);
+
+ if (pos != 0)
+ goto custom;
+
+ switch (weekday) {
+ case ICAL_SUNDAY_WEEKDAY:
+ day_mask |= 1 << 0;
+ break;
+
+ case ICAL_MONDAY_WEEKDAY:
+ day_mask |= 1 << 1;
+ break;
+
+ case ICAL_TUESDAY_WEEKDAY:
+ day_mask |= 1 << 2;
+ break;
+
+ case ICAL_WEDNESDAY_WEEKDAY:
+ day_mask |= 1 << 3;
+ break;
+
+ case ICAL_THURSDAY_WEEKDAY:
+ day_mask |= 1 << 4;
+ break;
+
+ case ICAL_FRIDAY_WEEKDAY:
+ day_mask |= 1 << 5;
+ break;
+
+ case ICAL_SATURDAY_WEEKDAY:
+ day_mask |= 1 << 6;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (ii == 0) {
+ struct icaltimetype dtstart;
+
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+
+ ii = icaltime_day_of_week (dtstart);
+ if (ii >= 1)
+ day_mask |= 1 << (ii - 1);
+ }
+
+ ndays = 0;
+
+ for (ii = 0; ii < 7; ii++) {
+ if ((day_mask & (1 << ii)) != 0)
+ ndays++;
+ }
+
+ out_recur->type = E_EWS_RECURRENCE_WEEKLY;
+ out_recur->recur.weekly.interval = rrule.interval;
+ out_recur->recur.weekly.days_of_week = 0;
+ out_recur->recur.weekly.first_day_of_week = G_DATE_BAD_WEEKDAY;
+
+ for (ii = 0; ii < 7 && ndays; ii++) {
+ if ((day_mask & (1 << ii)) != 0) {
+ switch (ii) {
+ case 0:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ break;
+ case 1:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ break;
+ case 2:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ break;
+ case 3:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ break;
+ case 4:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ break;
+ case 5:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ break;
+ case 6:
+ out_recur->recur.weekly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ break;
+ default:
+ g_warn_if_reached ();
+ break;
+ }
+ }
+ }
+ break;
+ }
+
+ case ICAL_MONTHLY_RECURRENCE: {
+ gint month_index = 1;
+ enum month_day_options month_day;
+ enum month_num_options month_num;
+
+ if (n_by_year_day != 0 ||
+ n_by_week_no != 0 ||
+ n_by_month != 0 ||
+ n_by_set_pos > 1)
+ goto custom;
+
+ if (n_by_month_day == 1) {
+ gint nth;
+
+ if (n_by_set_pos != 0)
+ goto custom;
+
+ nth = rrule.by_month_day[0];
+ if (nth < 1 && nth != -1)
+ goto custom;
+
+ if (nth == -1) {
+ struct icaltimetype dtstart;
+
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+
+ month_index = dtstart.day;
+ month_num = MONTH_NUM_LAST;
+ } else {
+ month_index = nth;
+ month_num = MONTH_NUM_DAY;
+ }
+ month_day = MONTH_DAY_NTH;
+
+ } else if (n_by_day == 1) {
+ enum icalrecurrencetype_weekday weekday;
+ gint pos;
+
+ weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[0]);
+ pos = icalrecurrencetype_day_position (rrule.by_day[0]);
+
+ if (pos == 0) {
+ if (n_by_set_pos != 1)
+ goto custom;
+ pos = rrule.by_set_pos[0];
+ } else if (pos < 0) {
+ goto custom;
+ }
+
+ switch (weekday) {
+ case ICAL_MONDAY_WEEKDAY:
+ month_day = MONTH_DAY_MON;
+ break;
+
+ case ICAL_TUESDAY_WEEKDAY:
+ month_day = MONTH_DAY_TUE;
+ break;
+
+ case ICAL_WEDNESDAY_WEEKDAY:
+ month_day = MONTH_DAY_WED;
+ break;
+
+ case ICAL_THURSDAY_WEEKDAY:
+ month_day = MONTH_DAY_THU;
+ break;
+
+ case ICAL_FRIDAY_WEEKDAY:
+ month_day = MONTH_DAY_FRI;
+ break;
+
+ case ICAL_SATURDAY_WEEKDAY:
+ month_day = MONTH_DAY_SAT;
+ break;
+
+ case ICAL_SUNDAY_WEEKDAY:
+ month_day = MONTH_DAY_SUN;
+ break;
+
+ default:
+ goto custom;
+ }
+
+ if (pos == -1)
+ month_num = MONTH_NUM_LAST;
+ else
+ month_num = pos - 1;
+ } else if (n_by_day > 1 && n_by_set_pos == 1 && n_by_month_day == 0) {
+ gint ii, pos;
+
+ pos = rrule.by_set_pos[0];
+ if (pos == -1)
+ month_num = MONTH_NUM_LAST;
+ else
+ month_num = pos - 1;
+
+ out_recur->type = E_EWS_RECURRENCE_RELATIVE_MONTHLY;
+ out_recur->recur.relative_monthly.interval = rrule.interval;
+ out_recur->recur.relative_monthly.days_of_week = 0;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+
+ for (ii = 0; rrule.by_day[ii] != ICAL_RECURRENCE_ARRAY_MAX; ii++) {
+ enum icalrecurrencetype_weekday weekday;
+
+ weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[ii]);
+ pos = icalrecurrencetype_day_position (rrule.by_day[ii]);
+
+ if (pos != 0)
+ goto custom;
+
+ switch (weekday) {
+ case ICAL_SUNDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ break;
+ case ICAL_MONDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ break;
+ case ICAL_TUESDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ break;
+ case ICAL_WEDNESDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ break;
+ case ICAL_THURSDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ break;
+ case ICAL_FRIDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ break;
+ case ICAL_SATURDAY_WEEKDAY:
+ out_recur->recur.relative_monthly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ break;
+ default:
+ break;
+ }
+ }
+
+ break;
+ } else {
+ goto custom;
+ }
+
+ out_recur->type = E_EWS_RECURRENCE_RELATIVE_MONTHLY;
+ out_recur->recur.relative_monthly.interval = rrule.interval;
+ out_recur->recur.relative_monthly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ out_recur->recur.relative_monthly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+
+ switch (month_day) {
+ case MONTH_DAY_NTH:
+ if (month_num == MONTH_NUM_LAST) {
+ out_recur->recur.relative_monthly.days_of_week =
e_ews_cal_util_month_index_to_days_of_week (month_index);
+ out_recur->recur.relative_monthly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST;
+ } else { /* month_num = MONTH_NUM_DAY; */
+ out_recur->type = E_EWS_RECURRENCE_ABSOLUTE_MONTHLY;
+ out_recur->recur.absolute_monthly.interval = rrule.interval;
+ out_recur->recur.absolute_monthly.day_of_month = month_index;
+ }
+ break;
+ case MONTH_DAY_MON:
+ out_recur->recur.relative_monthly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_TUE:
+ out_recur->recur.relative_monthly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_WED:
+ out_recur->recur.relative_monthly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_THU:
+ out_recur->recur.relative_monthly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_FRI:
+ out_recur->recur.relative_monthly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_SAT:
+ out_recur->recur.relative_monthly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_SUN:
+ out_recur->recur.relative_monthly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ out_recur->recur.relative_monthly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ }
+
+ break;
+ }
+
+ case ICAL_YEARLY_RECURRENCE: {
+ gint month_index = 1;
+ enum month_day_options month_day;
+ enum month_num_options month_num;
+
+ if (n_by_year_day != 0 ||
+ n_by_week_no != 0 ||
+ n_by_set_pos > 1 ||
+ rrule.interval > 1)
+ goto custom;
+
+ if (n_by_month_day == 1) {
+ gint nth;
+
+ if (n_by_set_pos != 0)
+ goto custom;
+
+ nth = rrule.by_month_day[0];
+ if (nth < 1 && nth != -1)
+ goto custom;
+
+ if (nth == -1) {
+ struct icaltimetype dtstart;
+
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+
+ month_index = dtstart.day;
+ month_num = MONTH_NUM_LAST;
+ } else {
+ month_index = nth;
+ month_num = MONTH_NUM_DAY;
+ }
+ month_day = MONTH_DAY_NTH;
+ }
+
+ if (n_by_day == 1) {
+ enum icalrecurrencetype_weekday weekday;
+ gint pos;
+
+ weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[0]);
+ pos = icalrecurrencetype_day_position (rrule.by_day[0]);
+
+ if (pos == 0) {
+ if (n_by_set_pos != 1)
+ goto custom;
+ pos = rrule.by_set_pos[0];
+ } else if (pos < 0) {
+ goto custom;
+ }
+
+ switch (weekday) {
+ case ICAL_MONDAY_WEEKDAY:
+ month_day = MONTH_DAY_MON;
+ break;
+
+ case ICAL_TUESDAY_WEEKDAY:
+ month_day = MONTH_DAY_TUE;
+ break;
+
+ case ICAL_WEDNESDAY_WEEKDAY:
+ month_day = MONTH_DAY_WED;
+ break;
+
+ case ICAL_THURSDAY_WEEKDAY:
+ month_day = MONTH_DAY_THU;
+ break;
+
+ case ICAL_FRIDAY_WEEKDAY:
+ month_day = MONTH_DAY_FRI;
+ break;
+
+ case ICAL_SATURDAY_WEEKDAY:
+ month_day = MONTH_DAY_SAT;
+ break;
+
+ case ICAL_SUNDAY_WEEKDAY:
+ month_day = MONTH_DAY_SUN;
+ break;
+
+ default:
+ goto custom;
+ }
+
+ if (pos == -1)
+ month_num = MONTH_NUM_LAST;
+ else
+ month_num = pos - 1;
+ }
+
+ out_recur->type = E_EWS_RECURRENCE_RELATIVE_YEARLY;
+ out_recur->recur.relative_yearly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ out_recur->recur.relative_yearly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+ out_recur->recur.relative_yearly.month = rrule.by_month[0];
+
+ if (n_by_day > 1 &&
+ n_by_month == 1 &&
+ n_by_set_pos == 1 &&
+ n_by_month_day == 0) {
+ gint ii, pos;
+
+ pos = rrule.by_set_pos[0];
+ if (pos == -1)
+ month_num = MONTH_NUM_LAST;
+ else
+ month_num = pos - 1;
+
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+
+ for (ii = 0; rrule.by_day[ii] != ICAL_RECURRENCE_ARRAY_MAX; ii++) {
+ enum icalrecurrencetype_weekday weekday;
+
+ weekday = icalrecurrencetype_day_day_of_week (rrule.by_day[ii]);
+ pos = icalrecurrencetype_day_position (rrule.by_day[ii]);
+
+ if (pos != 0)
+ goto custom;
+
+ switch (weekday) {
+ case ICAL_SUNDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ break;
+ case ICAL_MONDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ break;
+ case ICAL_TUESDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ break;
+ case ICAL_WEDNESDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ break;
+ case ICAL_THURSDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ break;
+ case ICAL_FRIDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ break;
+ case ICAL_SATURDAY_WEEKDAY:
+ out_recur->recur.relative_yearly.days_of_week |=
E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ break;
+ default:
+ break;
+ }
+ }
+ } else if (n_by_month == 1 &&
+ n_by_day == 1 &&
+ n_by_month_day == 0) {
+ switch (month_day) {
+ case MONTH_DAY_NTH:
+ if (month_num == MONTH_NUM_LAST) {
+ out_recur->recur.relative_yearly.days_of_week =
e_ews_cal_util_month_index_to_days_of_week (month_index);
+ out_recur->recur.relative_yearly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST;
+ } else { /* month_num = MONTH_NUM_DAY; */
+ out_recur->type = E_EWS_RECURRENCE_ABSOLUTE_YEARLY;
+ out_recur->recur.absolute_yearly.day_of_month = month_index;
+ out_recur->recur.absolute_yearly.month = rrule.by_month[0];
+ }
+ break;
+ case MONTH_DAY_MON:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_TUE:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_WED:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_THU:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_FRI:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_SAT:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ case MONTH_DAY_SUN:
+ out_recur->recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY;
+ out_recur->recur.relative_yearly.day_of_week_index =
e_ews_cal_util_month_num_to_day_of_week_index (month_num);
+ break;
+ }
+ } else if (n_by_month == 1 &&
+ n_by_month_day == 1 &&
+ n_by_day == 0) {
+ if (month_num == MONTH_NUM_LAST) {
+ out_recur->recur.relative_yearly.days_of_week =
e_ews_cal_util_month_index_to_days_of_week (month_index);
+ out_recur->recur.relative_yearly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST;
+ } else { /* month_num = MONTH_NUM_DAY; */
+ out_recur->type = E_EWS_RECURRENCE_ABSOLUTE_YEARLY;
+ out_recur->recur.absolute_yearly.day_of_month = month_index;
+ out_recur->recur.absolute_yearly.month = rrule.by_month[0];
+ }
+ } else if (n_by_day == 0 &&
+ n_by_month_day == 0 &&
+ n_by_month == 0) {
+ struct icaltimetype dtstart;
+
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+ if (icaltime_is_null_time (dtstart))
+ goto custom;
+
+ out_recur->type = E_EWS_RECURRENCE_ABSOLUTE_YEARLY;
+ out_recur->recur.absolute_yearly.day_of_month = dtstart.day;
+ out_recur->recur.absolute_yearly.month = dtstart.month;
+ } else {
+ goto custom;
+ }
+ } break;
+
+ default:
+ break;
+ }
+
+ if (out_recur->type != E_EWS_RECURRENCE_UNKNOWN) {
+ struct icaltimetype dtstart;
+
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+
+ out_recur->utc_start_date = icaltime_as_timet_with_zone (dtstart,
icaltimezone_get_utc_timezone ());
+
+ if (rrule.count) {
+ out_recur->end_type = E_EWS_RECURRENCE_END_NUMBERED;
+ out_recur->end.number_of_occurrences = rrule.count;
+ } else if (rrule.until.year) {
+ rrule.until.is_date = 1;
+
+ out_recur->end_type = E_EWS_RECURRENCE_END_DATE;
+ out_recur->end.utc_end_date = icaltime_as_timet_with_zone (rrule.until,
icaltimezone_get_utc_timezone ());
+ } else {
+ out_recur->end_type = E_EWS_RECURRENCE_END_NO_END;
+ }
+ }
+
+ return TRUE;
+
+ custom:
+
+ g_set_error (error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_CALENDARINVALIDRECURRENCE,
+ _("Cannot store this recurrence. Change it to simple single daily, weekly, monthly or yearly
recurrence without exceptions and with start date."));
+
+ return FALSE;
+}
+
+static void
+e_ews_cal_utils_write_days_of_week (ESoapMessage *msg,
+ guint32 days_of_week)
+{
+ GString *value;
+ guint32 weekdays, weekenddays;
+
+ g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
+
+ if (days_of_week == E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN)
+ return;
+
+ weekdays = E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ weekenddays = E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+
+ if ((days_of_week & weekdays) == weekdays && !(days_of_week & ~weekdays))
+ days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKDAY;
+ else if ((days_of_week & weekenddays) == weekenddays && !(days_of_week & ~weekenddays))
+ days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKENDDAY;
+
+ /* Do not localize, these are values used in XML */
+ if ((days_of_week & E_EWS_RECURRENCE_DAYS_OF_WEEK_DAY) != 0) {
+ value = g_string_new ("Day");
+ } else if ((days_of_week & E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKDAY) != 0) {
+ value = g_string_new ("Weekday");
+ } else if ((days_of_week & E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKENDDAY) != 0) {
+ value = g_string_new ("WeekendDay");
+ } else {
+ struct _bits {
+ EEwsRecurrenceDaysOfWeek n_bit;
+ const gchar *value;
+ } bits[] = {
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY, "Sunday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY, "Monday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY, "Tuesday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY, "Wednesday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY, "Thursday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY, "Friday" },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY, "Saturday" }
+ };
+ gint ii;
+
+ value = g_string_new ("");
+
+ for (ii = 0; ii < G_N_ELEMENTS (bits); ii++) {
+ if ((days_of_week & bits[ii].n_bit) != 0) {
+ if (value->len)
+ g_string_append_c (value, ' ');
+
+ g_string_append (value, bits[ii].value);
+ }
+ }
+ }
+
+ if (value->len) {
+ e_soap_message_start_element (msg, "DaysOfWeek", NULL, NULL);
+ e_soap_message_write_string (msg, value->str);
+ e_soap_message_end_element (msg); /* DaysOfWeek */
+ }
+
+ g_string_free (value, TRUE);
+}
+
+static void
+e_ews_cal_utils_write_day_of_week_index (ESoapMessage *msg,
+ EEwsRecurrenceDayOfWeekIndex day_of_week_index)
+{
+ const gchar *value = NULL;
+
+ g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
+
+ /* Do not localize, these are values used in XML */
+ switch (day_of_week_index) {
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN:
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FIRST:
+ value = "First";
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_SECOND:
+ value = "Second";
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_THIRD:
+ value = "Third";
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FOURTH:
+ value = "Fourth";
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST:
+ value = "Last";
+ break;
+ }
+
+ if (value) {
+ e_soap_message_start_element (msg, "DayOfWeekIndex", NULL, NULL);
+ e_soap_message_write_string (msg, value);
+ e_soap_message_end_element (msg); /* DayOfWeekIndex */
+ }
+}
+
+static void
+e_ews_cal_utils_write_month (ESoapMessage *msg,
+ GDateMonth month)
+{
+ const gchar *value = NULL;
+
+ g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
+
+ /* Do not localize, these are values used in XML */
+ switch (month) {
+ case G_DATE_BAD_MONTH:
+ break;
+ case G_DATE_JANUARY:
+ value = "January";
+ break;
+ case G_DATE_FEBRUARY:
+ value = "February";
+ break;
+ case G_DATE_MARCH:
+ value = "March";
+ break;
+ case G_DATE_APRIL:
+ value = "April";
+ break;
+ case G_DATE_MAY:
+ value = "May";
+ break;
+ case G_DATE_JUNE:
+ value = "June";
+ break;
+ case G_DATE_JULY:
+ value = "July";
+ break;
+ case G_DATE_AUGUST:
+ value = "August";
+ break;
+ case G_DATE_SEPTEMBER:
+ value = "September";
+ break;
+ case G_DATE_OCTOBER:
+ value = "October";
+ break;
+ case G_DATE_NOVEMBER:
+ value = "November";
+ break;
+ case G_DATE_DECEMBER:
+ value = "December";
+ break;
+ }
+
+ if (value) {
+ e_soap_message_start_element (msg, "Month", NULL, NULL);
+ e_soap_message_write_string (msg, value);
+ e_soap_message_end_element (msg); /* Month */
+ }
+}
+
+static void
+e_ews_cal_util_write_utc_date (ESoapMessage *msg,
+ const gchar *name,
+ time_t utc_date)
+{
+ struct icaltimetype itt;
+ gchar *value;
+
+ g_return_if_fail (E_IS_SOAP_MESSAGE (msg));
+ g_return_if_fail (name != NULL);
+
+ itt = icaltime_from_timet_with_zone (utc_date, 1, icaltimezone_get_utc_timezone ());
+ value = g_strdup_printf ("%04d-%02d-%02dZ", itt.year, itt.month, itt.day);
+
+ e_soap_message_start_element (msg, name, NULL, NULL);
+ e_soap_message_write_string (msg, value);
+ e_soap_message_end_element (msg);
+
+ g_free (value);
+}
+
+/* Writes 'Recurrence' element into the @msg. Sets the @error only if the RRULE
+ cannot be transformed into Recurrence */
+gboolean
+e_ews_cal_utils_set_recurrence (ESoapMessage *msg,
+ icalcomponent *comp,
+ gboolean server_satisfies_2013,
+ GError **error)
+{
+ EEwsRecurrence recur;
+
+ g_return_val_if_fail (E_IS_SOAP_MESSAGE (msg), FALSE);
+ g_return_val_if_fail (comp != NULL, FALSE);
+
+ recur.type = E_EWS_RECURRENCE_UNKNOWN;
+ recur.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+
+ if (!e_ews_cal_utils_convert_recurrence (comp, &recur, error))
+ return FALSE;
+
+ if (recur.type == E_EWS_RECURRENCE_UNKNOWN ||
+ recur.end_type == E_EWS_RECURRENCE_END_UNKNOWN) {
+ return TRUE;
+ }
+
+ e_soap_message_start_element (msg, "Recurrence", NULL, NULL);
+
+ switch (recur.type) {
+ case E_EWS_RECURRENCE_UNKNOWN:
+ g_warn_if_reached ();
+ break;
+ case E_EWS_RECURRENCE_RELATIVE_YEARLY:
+ e_soap_message_start_element (msg, "RelativeYearlyRecurrence", NULL, NULL);
+ e_ews_cal_utils_write_days_of_week (msg, recur.recur.relative_yearly.days_of_week);
+ e_ews_cal_utils_write_day_of_week_index (msg, recur.recur.relative_yearly.day_of_week_index);
+ e_ews_cal_utils_write_month (msg, recur.recur.relative_yearly.month);
+ e_soap_message_end_element (msg); /* RelativeYearlyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_ABSOLUTE_YEARLY:
+ e_soap_message_start_element (msg, "AbsoluteYearlyRecurrence", NULL, NULL);
+ e_soap_message_start_element (msg, "DayOfMonth", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.absolute_yearly.day_of_month);
+ e_soap_message_end_element (msg); /* DayOfMonth */
+ e_ews_cal_utils_write_month (msg, recur.recur.absolute_yearly.month);
+ e_soap_message_end_element (msg); /* AbsoluteYearlyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_RELATIVE_MONTHLY:
+ e_soap_message_start_element (msg, "RelativeMonthlyRecurrence", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.relative_monthly.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_ews_cal_utils_write_days_of_week (msg, recur.recur.relative_monthly.days_of_week);
+ e_ews_cal_utils_write_day_of_week_index (msg, recur.recur.relative_monthly.day_of_week_index);
+ e_soap_message_end_element (msg); /* RelativeMonthlyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_ABSOLUTE_MONTHLY:
+ e_soap_message_start_element (msg, "AbsoluteMonthlyRecurrence", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.absolute_monthly.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_start_element (msg, "DayOfMonth", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.absolute_monthly.day_of_month);
+ e_soap_message_end_element (msg); /* DayOfMonth */
+ e_soap_message_end_element (msg); /* AbsoluteMonthlyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_WEEKLY:
+ e_soap_message_start_element (msg, "WeeklyRecurrence", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.weekly.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_ews_cal_utils_write_days_of_week (msg, recur.recur.weekly.days_of_week);
+ if (server_satisfies_2013) {
+ const gchar *value = NULL;
+
+ switch (recur.recur.weekly.first_day_of_week) {
+ case G_DATE_BAD_WEEKDAY:
+ break;
+ case G_DATE_MONDAY:
+ value = "Monday";
+ break;
+ case G_DATE_TUESDAY:
+ value = "Tuesday";
+ break;
+ case G_DATE_WEDNESDAY:
+ value = "Wednesday";
+ break;
+ case G_DATE_THURSDAY:
+ value = "Thursday";
+ break;
+ case G_DATE_FRIDAY:
+ value = "Friday";
+ break;
+ case G_DATE_SATURDAY:
+ value = "Saturday";
+ break;
+ case G_DATE_SUNDAY:
+ value = "Sunday";
+ break;
+ }
+
+ if (value) {
+ e_soap_message_start_element (msg, "FirstDayOfWeek", NULL, NULL);
+ e_soap_message_write_string (msg, value);
+ e_soap_message_end_element (msg); /* FirstDayOfWeek */
+ }
+ }
+ e_soap_message_end_element (msg); /* WeeklyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_DAILY:
+ e_soap_message_start_element (msg, "DailyRecurrence", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_end_element (msg); /* DailyRecurrence */
+ break;
+ case E_EWS_RECURRENCE_DAILY_REGENERATION:
+ e_soap_message_start_element (msg, "DailyRegeneration", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_end_element (msg); /* DailyRegeneration */
+ break;
+ case E_EWS_RECURRENCE_WEEKLY_REGENERATION:
+ e_soap_message_start_element (msg, "WeeklyRegeneration", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_end_element (msg); /* WeeklyRegeneration */
+ break;
+ case E_EWS_RECURRENCE_MONTHLY_REGENERATION:
+ e_soap_message_start_element (msg, "MonthlyRegeneration", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_end_element (msg); /* MonthlyRegeneration */
+ break;
+ case E_EWS_RECURRENCE_YEARLY_REGENERATION:
+ e_soap_message_start_element (msg, "YearlyRegeneration", NULL, NULL);
+ e_soap_message_start_element (msg, "Interval", NULL, NULL);
+ e_soap_message_write_int (msg, recur.recur.interval);
+ e_soap_message_end_element (msg); /* Interval */
+ e_soap_message_end_element (msg); /* YearlyRegeneration */
+ break;
+ }
+
+ switch (recur.end_type) {
+ case E_EWS_RECURRENCE_END_UNKNOWN:
+ g_warn_if_reached ();
+ break;
+ case E_EWS_RECURRENCE_END_NO_END:
+ e_soap_message_start_element (msg, "NoEndRecurrence", NULL, NULL);
+ e_ews_cal_util_write_utc_date (msg, "StartDate", recur.utc_start_date);
+ e_soap_message_end_element (msg); /* NoEndRecurrence */
+ break;
+ case E_EWS_RECURRENCE_END_DATE:
+ e_soap_message_start_element (msg, "EndDateRecurrence", NULL, NULL);
+ e_ews_cal_util_write_utc_date (msg, "StartDate", recur.utc_start_date);
+ e_ews_cal_util_write_utc_date (msg, "EndDate", recur.end.utc_end_date);
+ e_soap_message_end_element (msg); /* EndDateRecurrence */
+ break;
+ case E_EWS_RECURRENCE_END_NUMBERED:
+ e_soap_message_start_element (msg, "NumberedRecurrence", NULL, NULL);
+ e_ews_cal_util_write_utc_date (msg, "StartDate", recur.utc_start_date);
+ e_soap_message_start_element (msg, "NumberOfOccurrences", NULL, NULL);
+ e_soap_message_write_int (msg, recur.end.number_of_occurrences);
+ e_soap_message_end_element (msg); /* NumberOfOccurrences */
+ e_soap_message_end_element (msg); /* NumberedRecurrence */
+ break;
+ }
+
+ e_soap_message_end_element (msg); /* Recurrence */
+
+ return TRUE;
+}
+
+static void
+e_ews_cal_utils_days_of_week_to_rrule (struct icalrecurrencetype *rrule,
+ guint32 days_of_week)
+{
+ struct _bits {
+ EEwsRecurrenceDaysOfWeek bit;
+ icalrecurrencetype_weekday week_day;
+ } bits[] = {
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY, ICAL_SUNDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY, ICAL_MONDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY, ICAL_TUESDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY, ICAL_WEDNESDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY, ICAL_THURSDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY, ICAL_FRIDAY_WEEKDAY },
+ { E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY, ICAL_SATURDAY_WEEKDAY }
+ };
+ gint ii, idx;
+
+ g_return_if_fail (rrule != NULL);
+
+ if ((days_of_week & E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKDAY) != 0) {
+ days_of_week |= E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY |
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY;
+ } else if ((days_of_week & E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKENDDAY) != 0) {
+ days_of_week |= E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY | E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY;
+ }
+
+ idx = 0;
+
+ for (ii = 0; ii < G_N_ELEMENTS (bits); ii++) {
+ if ((days_of_week & bits[ii].bit) != 0) {
+ rrule->by_day[idx] = bits[ii].week_day;
+ idx++;
+ }
+ }
+
+ rrule->by_day[idx] = ICAL_RECURRENCE_ARRAY_MAX;
+}
+
+static void
+e_ews_cal_utils_day_of_week_index_to_rrule (struct icalrecurrencetype *rrule,
+ EEwsRecurrenceDayOfWeekIndex day_of_week_index)
+{
+ g_return_if_fail (rrule != NULL);
+
+ switch (day_of_week_index) {
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN:
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FIRST:
+ rrule->by_set_pos[0] = 1;
+ rrule->by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_SECOND:
+ rrule->by_set_pos[0] = 2;
+ rrule->by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_THIRD:
+ rrule->by_set_pos[0] = 3;
+ rrule->by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FOURTH:
+ rrule->by_set_pos[0] = 4;
+ rrule->by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ case E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST:
+ rrule->by_set_pos[0] = -1;
+ rrule->by_set_pos[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ }
+}
+
+static void
+e_ews_cal_utils_month_to_rrule (struct icalrecurrencetype *rrule,
+ GDateMonth month)
+{
+ g_return_if_fail (rrule != NULL);
+
+ if (month >= G_DATE_JANUARY && month <= G_DATE_DECEMBER) {
+ rrule->by_month[0] = month;
+ rrule->by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ }
+}
+
+/* Does nothing when the 'item' doesn't contain any recurrence */
+void
+e_ews_cal_utils_recurrence_to_rrule (EEwsItem *item,
+ icalcomponent *comp)
+{
+ EEwsRecurrence recur;
+ struct icalrecurrencetype rrule;
+ struct icaltimetype recur_start;
+ gboolean usable = FALSE;
+
+ g_return_if_fail (E_IS_EWS_ITEM (item));
+ g_return_if_fail (comp != NULL);
+
+ e_cal_util_remove_property_by_kind (comp, ICAL_RRULE_PROPERTY, TRUE);
+ e_cal_util_remove_property_by_kind (comp, ICAL_RDATE_PROPERTY, TRUE);
+ e_cal_util_remove_property_by_kind (comp, ICAL_EXRULE_PROPERTY, TRUE);
+ e_cal_util_remove_property_by_kind (comp, ICAL_EXDATE_PROPERTY, TRUE);
+ e_cal_util_remove_x_property (comp, X_EWS_TASK_REGENERATION);
+
+ if (!e_ews_item_get_recurrence (item, &recur))
+ return;
+
+ icalrecurrencetype_clear (&rrule);
+ recur_start = icaltime_from_timet_with_zone (recur.utc_start_date, 1, icaltimezone_get_utc_timezone
());
+
+ switch (recur.end_type) {
+ case E_EWS_RECURRENCE_END_UNKNOWN:
+ break;
+ case E_EWS_RECURRENCE_END_NO_END:
+ rrule.until = icaltime_null_time ();
+ rrule.count = 0;
+ usable = TRUE;
+ break;
+ case E_EWS_RECURRENCE_END_DATE:
+ rrule.until = icaltime_from_timet_with_zone (recur.end.utc_end_date, 1,
icaltimezone_get_utc_timezone ());
+ rrule.count = 0;
+ usable = !icaltime_is_null_time (rrule.until) && icaltime_is_valid_time (rrule.until);
+ break;
+ case E_EWS_RECURRENCE_END_NUMBERED:
+ rrule.until = icaltime_null_time ();
+ rrule.count = recur.end.number_of_occurrences;
+ usable = rrule.count > 0;
+ break;
+ }
+
+ if (!usable) {
+ g_warning ("%s: Cannot decode end condition in received recurrence", G_STRFUNC);
+ return;
+ }
+
+ usable = FALSE;
+
+ switch (recur.type) {
+ case E_EWS_RECURRENCE_UNKNOWN:
+ break;
+ case E_EWS_RECURRENCE_RELATIVE_YEARLY:
+ usable = TRUE;
+ rrule.freq = ICAL_YEARLY_RECURRENCE;
+ rrule.interval = 1;
+ e_ews_cal_utils_days_of_week_to_rrule (&rrule, recur.recur.relative_yearly.days_of_week);
+ e_ews_cal_utils_day_of_week_index_to_rrule (&rrule,
recur.recur.relative_yearly.day_of_week_index);
+ e_ews_cal_utils_month_to_rrule (&rrule, recur.recur.relative_yearly.month);
+ break;
+ case E_EWS_RECURRENCE_ABSOLUTE_YEARLY:
+ usable = TRUE;
+ rrule.freq = ICAL_YEARLY_RECURRENCE;
+ rrule.interval = 1;
+ if (icaltime_is_valid_time (recur_start) &&
+ recur_start.month == recur.recur.absolute_yearly.month &&
+ recur_start.day == recur.recur.absolute_yearly.day_of_month) {
+ /* This is how evolution uses it, derive date from the DTSTART */
+ } else {
+ rrule.by_month_day[0] = recur.recur.absolute_yearly.day_of_month;
+ rrule.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ e_ews_cal_utils_month_to_rrule (&rrule, recur.recur.absolute_yearly.month);
+ }
+ break;
+ case E_EWS_RECURRENCE_RELATIVE_MONTHLY:
+ usable = TRUE;
+ rrule.freq = ICAL_MONTHLY_RECURRENCE;
+ rrule.interval = recur.recur.relative_monthly.interval;
+ e_ews_cal_utils_days_of_week_to_rrule (&rrule, recur.recur.relative_monthly.days_of_week);
+ e_ews_cal_utils_day_of_week_index_to_rrule (&rrule,
recur.recur.relative_monthly.day_of_week_index);
+ break;
+ case E_EWS_RECURRENCE_ABSOLUTE_MONTHLY:
+ usable = TRUE;
+ rrule.freq = ICAL_MONTHLY_RECURRENCE;
+ rrule.interval = recur.recur.absolute_monthly.interval;
+ rrule.by_month_day[0] = recur.recur.absolute_monthly.day_of_month;
+ rrule.by_month_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
+ break;
+ case E_EWS_RECURRENCE_WEEKLY:
+ usable = TRUE;
+ rrule.freq = ICAL_WEEKLY_RECURRENCE;
+ rrule.interval = recur.recur.weekly.interval;
+ e_ews_cal_utils_days_of_week_to_rrule (&rrule, recur.recur.weekly.days_of_week);
+ break;
+ case E_EWS_RECURRENCE_DAILY:
+ usable = TRUE;
+ rrule.freq = ICAL_DAILY_RECURRENCE;
+ rrule.interval = recur.recur.interval;
+ break;
+ case E_EWS_RECURRENCE_DAILY_REGENERATION:
+ case E_EWS_RECURRENCE_WEEKLY_REGENERATION:
+ case E_EWS_RECURRENCE_MONTHLY_REGENERATION:
+ case E_EWS_RECURRENCE_YEARLY_REGENERATION:
+ e_ews_cal_util_encode_regeneration (&recur, comp);
+ return;
+ }
+
+ if (usable) {
+ struct icaltimetype itt;
+
+ itt = icaltime_from_timet_with_zone (recur.utc_start_date, 1, icaltimezone_get_utc_timezone
());
+
+ if (!icaltime_is_null_time (itt) && icaltime_is_valid_time (itt)) {
+ icalproperty *prop;
+
+ icalcomponent_set_dtstart (comp, itt);
+
+ prop = icalproperty_new_rrule (rrule);
+ icalcomponent_add_property (comp, prop);
+ } else {
+ g_warning ("%s: Cannot decode start date in received recurrence", G_STRFUNC);
+ }
+ } else {
+ g_warning ("%s: Cannot decode received recurrence", G_STRFUNC);
+ }
+}
diff --git a/src/server/e-ews-calendar-utils.h b/src/server/e-ews-calendar-utils.h
index 6419a7b..3cfe536 100644
--- a/src/server/e-ews-calendar-utils.h
+++ b/src/server/e-ews-calendar-utils.h
@@ -24,22 +24,35 @@
#include <libical/ical.h>
#include "server/e-soap-message.h"
+#include "server/e-ews-item.h"
G_BEGIN_DECLS
+/* Custom property, because evolution cannot cope with it,
+ but it shouldn't lost it as well */
+#define X_EWS_TASK_REGENERATION "X-EWS-TASK-REGENERATION"
+
typedef struct _EEWSFreeBusyData {
time_t period_start;
time_t period_end;
GSList *user_mails; /* gchar * */
} EEWSFreeBusyData;
-void e_ews_cal_utils_prepare_free_busy_request
+gboolean e_ews_cal_utils_prepare_free_busy_request
(ESoapMessage *msg,
- gpointer user_data); /* EEWSFreeBusyData * */
+ gpointer user_data, /* EEWSFreeBusyData * */
+ GError **error);
void e_ews_cal_utils_set_time (ESoapMessage *msg,
const gchar *name,
icaltimetype *tt,
gboolean with_timezone);
+gboolean e_ews_cal_utils_set_recurrence (ESoapMessage *msg,
+ icalcomponent *comp,
+ gboolean server_satisfies_2013,
+ GError **error);
+void e_ews_cal_utils_recurrence_to_rrule
+ (EEwsItem *item,
+ icalcomponent *comp);
G_END_DECLS
diff --git a/src/server/e-ews-camel-common.c b/src/server/e-ews-camel-common.c
index ebdb529..71acba1 100644
--- a/src/server/e-ews-camel-common.c
+++ b/src/server/e-ews-camel-common.c
@@ -107,9 +107,10 @@ write_recipients (ESoapMessage *msg,
#define MAPI_MSGFLAG_READ 0x01
#define MAPI_MSGFLAG_UNSENT 0x08
-static void
+static gboolean
create_mime_message_cb (ESoapMessage *msg,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
struct _create_mime_msg_data *create_data = user_data;
CamelStream *mem, *filtered;
@@ -323,6 +324,8 @@ create_mime_message_cb (ESoapMessage *msg,
e_soap_message_end_element (msg); /* Message */
g_free (create_data);
+
+ return TRUE;
}
gboolean
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index a0bae8b..ca0913c 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -5322,6 +5322,8 @@ e_ews_connection_update_items (EEwsConnection *cnc,
ESoapMessage *msg;
GSimpleAsyncResult *simple;
EwsAsyncData *async_data;
+ gboolean success;
+ GError *local_error = NULL;
g_return_if_fail (cnc != NULL);
@@ -5360,7 +5362,7 @@ e_ews_connection_update_items (EEwsConnection *cnc,
e_soap_message_start_element (msg, "ItemChanges", "messages", NULL);
- create_cb (msg, create_user_data);
+ success = create_cb (msg, create_user_data, &local_error);
e_soap_message_end_element (msg); /* ItemChanges */
@@ -5374,18 +5376,26 @@ e_ews_connection_update_items (EEwsConnection *cnc,
g_simple_async_result_set_op_res_gpointer (
simple, async_data, (GDestroyNotify) async_data_free);
+ if (!success) {
+ if (local_error)
+ g_simple_async_result_take_error (simple, local_error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_clear_object (&msg);
+
/*
* We need to check for both namespaces, because, the message is being wrote without use the types
* namespace. Maybe it is wrong, but the server doesn't complain about that. But this is the reason
* for the first check. The second one, is related to "how it should be" accord with EWS
specifications.
*/
- if (!element_has_child (msg, "/s:Envelope/s:Body/m:UpdateItem/m:ItemChanges/ItemChange/Updates") &&
- !element_has_child (msg,
"/s:Envelope/s:Body/m:UpdateItem/m:ItemChanges/t:ItemChange/t:Updates"))
+ } else if (!element_has_child (msg,
"/s:Envelope/s:Body/m:UpdateItem/m:ItemChanges/ItemChange/Updates") &&
+ !element_has_child (msg,
"/s:Envelope/s:Body/m:UpdateItem/m:ItemChanges/t:ItemChange/t:Updates")) {
g_simple_async_result_complete_in_idle (simple);
- else
+ g_clear_object (&msg);
+ } else {
e_ews_connection_queue_request (
cnc, msg, get_items_response_cb,
pri, cancellable, simple);
+ }
g_object_unref (simple);
}
@@ -5487,6 +5497,8 @@ e_ews_connection_create_items (EEwsConnection *cnc,
ESoapMessage *msg;
GSimpleAsyncResult *simple;
EwsAsyncData *async_data;
+ gboolean success;
+ GError *local_error = NULL;
g_return_if_fail (cnc != NULL);
@@ -5519,7 +5531,7 @@ e_ews_connection_create_items (EEwsConnection *cnc,
e_soap_message_start_element (msg, "Items", "messages", NULL);
- create_cb (msg, create_user_data);
+ success = create_cb (msg, create_user_data, &local_error);
e_soap_message_end_element (msg); /* Items */
@@ -5533,9 +5545,16 @@ e_ews_connection_create_items (EEwsConnection *cnc,
g_simple_async_result_set_op_res_gpointer (
simple, async_data, (GDestroyNotify) async_data_free);
- e_ews_connection_queue_request (
- cnc, msg, get_items_response_cb,
- pri, cancellable, simple);
+ if (success) {
+ e_ews_connection_queue_request (
+ cnc, msg, get_items_response_cb,
+ pri, cancellable, simple);
+ } else {
+ if (local_error)
+ g_simple_async_result_take_error (simple, local_error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_clear_object (&msg);
+ }
g_object_unref (simple);
}
@@ -6102,6 +6121,8 @@ e_ews_connection_update_folder (EEwsConnection *cnc,
ESoapMessage *msg;
GSimpleAsyncResult *simple;
EwsAsyncData *async_data;
+ gboolean success;
+ GError *local_error = NULL;
g_return_if_fail (cnc != NULL);
@@ -6119,7 +6140,7 @@ e_ews_connection_update_folder (EEwsConnection *cnc,
e_soap_message_start_element (msg, "FolderChanges", "messages", NULL);
- create_cb (msg, create_user_data);
+ success = create_cb (msg, create_user_data, &local_error);
e_soap_message_end_element (msg); /* FolderChanges */
@@ -6133,9 +6154,16 @@ e_ews_connection_update_folder (EEwsConnection *cnc,
g_simple_async_result_set_op_res_gpointer (
simple, async_data, (GDestroyNotify) async_data_free);
- e_ews_connection_queue_request (
- cnc, msg, update_folder_response_cb,
- pri, cancellable, simple);
+ if (success) {
+ e_ews_connection_queue_request (
+ cnc, msg, update_folder_response_cb,
+ pri, cancellable, simple);
+ } else {
+ if (local_error)
+ g_simple_async_result_take_error (simple, local_error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_clear_object (&msg);
+ }
g_object_unref (simple);
}
@@ -7974,6 +8002,8 @@ e_ews_connection_get_free_busy (EEwsConnection *cnc,
ESoapMessage *msg;
GSimpleAsyncResult *simple;
EwsAsyncData *async_data;
+ gboolean success;
+ GError *local_error = NULL;
g_return_if_fail (cnc != NULL);
@@ -7989,7 +8019,7 @@ e_ews_connection_get_free_busy (EEwsConnection *cnc,
FALSE,
TRUE);
- free_busy_cb (msg, free_busy_user_data);
+ success = free_busy_cb (msg, free_busy_user_data, &local_error);
e_ews_message_write_footer (msg); /*GetUserAvailabilityRequest */
@@ -8001,9 +8031,16 @@ e_ews_connection_get_free_busy (EEwsConnection *cnc,
g_simple_async_result_set_op_res_gpointer (
simple, async_data, (GDestroyNotify) async_data_free);
- e_ews_connection_queue_request (
- cnc, msg, get_free_busy_response_cb,
- pri, cancellable, simple);
+ if (success) {
+ e_ews_connection_queue_request (
+ cnc, msg, get_free_busy_response_cb,
+ pri, cancellable, simple);
+ } else {
+ if (local_error)
+ g_simple_async_result_take_error (simple, local_error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_clear_object (&msg);
+ }
g_object_unref (simple);
}
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index 108205f..fbbad84 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -80,8 +80,9 @@ enum {
EWS_PRIORITY_HIGH
};
-typedef void (*EEwsRequestCreationCallback) (ESoapMessage *msg,
- gpointer user_data);
+typedef gboolean(*EEwsRequestCreationCallback) (ESoapMessage *msg,
+ gpointer user_data,
+ GError **error);
typedef void (*EwsProgressFn) (gpointer object,
gint percent);
typedef void (*EEwsResponseCallback) (ESoapResponse *response,
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index e92475a..a5b99bf 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -29,6 +29,7 @@
#include <glib/gstdio.h>
#include <glib/gprintf.h>
#include <libsoup/soup-misc.h>
+#include <libical/ical.h>
#include "e-ews-item.h"
#include "e-ews-item-change.h"
@@ -151,6 +152,7 @@ struct _EEwsItemPrivate {
gboolean reminder_is_set;
time_t reminder_due_by;
gint reminder_minutes_before_start;
+ EEwsRecurrence recurrence;
struct _EEwsContactFields *contact_fields;
struct _EEwsTaskFields *task_fields;
@@ -312,6 +314,8 @@ e_ews_item_init (EEwsItem *item)
item->priv->reminder_is_set = FALSE;
item->priv->reminder_minutes_before_start = -1;
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
}
static void
@@ -376,24 +380,35 @@ ews_item_free_attendee (EwsAttendee *attendee)
}
static time_t
-ews_item_parse_date (const gchar *dtstring)
+ews_item_parse_date (ESoapParameter *param)
{
time_t t = 0;
GTimeVal t_val;
+ gchar *dtstring;
+ gint len;
+
+ dtstring = e_soap_parameter_get_string_value (param);
g_return_val_if_fail (dtstring != NULL, 0);
+ len = strlen (dtstring);
if (g_time_val_from_iso8601 (dtstring, &t_val)) {
t = (time_t) t_val.tv_sec;
- } else if (strlen (dtstring) == 8) {
+ } else if (len == 8 || (len == 11 && dtstring[4] == '-' && dtstring[7] == '-' && dtstring[10] ==
'Z')) {
/* It might be a date value */
- GDate date;
- struct tm tt;
guint16 year;
guint month;
guint8 day;
- g_date_clear (&date, 1);
+ if (len == 11) {
+ dtstring[4] = dtstring[5];
+ dtstring[5] = dtstring[6];
+ dtstring[6] = dtstring[8];
+ dtstring[7] = dtstring[9];
+ dtstring[8] = dtstring[10];
+ dtstring[9] = '\0';
+ }
+
#define digit_at(x,y) (x[y] - '0')
year = digit_at (dtstring, 0) * 1000
+ digit_at (dtstring, 1) * 100
@@ -402,15 +417,33 @@ ews_item_parse_date (const gchar *dtstring)
month = digit_at (dtstring, 4) * 10 + digit_at (dtstring, 5);
day = digit_at (dtstring, 6) * 10 + digit_at (dtstring, 7);
- g_date_set_year (&date, year);
- g_date_set_month (&date, month);
- g_date_set_day (&date, day);
+ if (len == 11) {
+ struct icaltimetype itt;
- g_date_to_struct_tm (&date, &tt);
- t = mktime (&tt);
+ itt = icaltime_null_time ();
+ itt.year = year;
+ itt.month = month;
+ itt.day = day;
+ itt.is_date = 1;
+ itt.zone = icaltimezone_get_utc_timezone ();
+ t = icaltime_as_timet_with_zone (itt, icaltimezone_get_utc_timezone ());
+ } else {
+ GDate date;
+ struct tm tt;
+
+ g_date_clear (&date, 1);
+ g_date_set_year (&date, year);
+ g_date_set_month (&date, month);
+ g_date_set_day (&date, day);
+
+ g_date_to_struct_tm (&date, &tt);
+ t = mktime (&tt);
+ }
} else
- g_warning ("Could not parse the string \n");
+ g_warning ("%s: Could not parse the string '%s'", G_STRFUNC, dtstring ? dtstring : "[null]");
+
+ g_free (dtstring);
return t;
}
@@ -766,7 +799,6 @@ parse_contact_field (EEwsItem *item,
ESoapParameter *subparam)
{
EEwsItemPrivate *priv = item->priv;
- gchar *value = NULL;
if (!g_ascii_strcasecmp (name, "Culture")) {
priv->contact_fields->culture = e_soap_parameter_get_string_value (subparam);
@@ -790,9 +822,7 @@ parse_contact_field (EEwsItem *item,
} else if (!g_ascii_strcasecmp (name, "AssistantName")) {
priv->contact_fields->assistant_name = e_soap_parameter_get_string_value (subparam);
} else if (!g_ascii_strcasecmp (name, "Birthday")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->contact_fields->birthday = ews_item_parse_date (value);
- g_free (value);
+ priv->contact_fields->birthday = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "BusinessHomePage")) {
priv->contact_fields->business_homepage = e_soap_parameter_get_string_value (subparam);
} else if (!g_ascii_strcasecmp (name, "Department")) {
@@ -817,9 +847,7 @@ parse_contact_field (EEwsItem *item,
} else if (!g_ascii_strcasecmp (name, "MiddleName")) {
priv->contact_fields->middlename = e_soap_parameter_get_string_value (subparam);
} else if (!g_ascii_strcasecmp (name, "WeddingAnniversary")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->contact_fields->wedding_anniversary = ews_item_parse_date (value);
- g_free (value);
+ priv->contact_fields->wedding_anniversary = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "Body")) {
/*
* For Exchange versions >= 2010_SP2 Notes property can be get
@@ -830,6 +858,460 @@ parse_contact_field (EEwsItem *item,
}
}
+static guint32 /* bit-or of EEwsRecurrenceDaysOfWeek */
+parse_recur_days_of_week (ESoapParameter *param)
+{
+ struct _keys {
+ const gchar *str_value;
+ EEwsRecurrenceDaysOfWeek bit_value;
+ } keys[] = {
+ /* Do not localize, these are values used in XML */
+ { "Sunday", E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY },
+ { "Monday", E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY },
+ { "Tuesday", E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY },
+ { "Wednesday", E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY },
+ { "Thursday", E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY },
+ { "Friday", E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY },
+ { "Saturday", E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY },
+ { "Day", E_EWS_RECURRENCE_DAYS_OF_WEEK_DAY },
+ { "Weekday", E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKDAY },
+ { "WeekendDay", E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKENDDAY }
+ };
+ gchar *value, **split_value;
+ guint32 days_of_week = 0;
+ gint ii, jj;
+
+ g_return_val_if_fail (param != NULL, E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN);
+
+ value = e_soap_parameter_get_string_value (param);
+ if (!value || !*value) {
+ g_free (value);
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ }
+
+ split_value = g_strsplit (value, " ", -1);
+
+ for (ii = 0; split_value && split_value[ii]; ii++) {
+ const gchar *str = split_value[ii];
+
+ if (!str || !*str)
+ continue;
+
+ for (jj = 0; jj < G_N_ELEMENTS (keys); jj++) {
+ if (g_strcmp0 (str, keys[jj].str_value) == 0) {
+ days_of_week |= keys[jj].bit_value;
+ break;
+ }
+ }
+ }
+
+ g_strfreev (split_value);
+ g_free (value);
+
+ return days_of_week;
+}
+
+static EEwsRecurrenceDayOfWeekIndex
+parse_recur_day_of_week_index (ESoapParameter *param)
+{
+ EEwsRecurrenceDayOfWeekIndex day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+ gchar *value;
+
+ g_return_val_if_fail (param != NULL, E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN);
+
+ value = e_soap_parameter_get_string_value (param);
+ if (!value || !*value) {
+ g_free (value);
+ return E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ }
+
+ /* Do not localize, these are values used in XML */
+ if (g_strcmp0 (value, "First") == 0)
+ day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FIRST;
+ else if (g_strcmp0 (value, "Second") == 0)
+ day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_SECOND;
+ else if (g_strcmp0 (value, "Third") == 0)
+ day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_THIRD;
+ else if (g_strcmp0 (value, "Fourth") == 0)
+ day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FOURTH;
+ else if (g_strcmp0 (value, "Last") == 0)
+ day_of_week_index = E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST;
+
+ g_free (value);
+
+ return day_of_week_index;
+}
+
+static GDateMonth
+parse_recur_month (ESoapParameter *param)
+{
+ GDateMonth month = G_DATE_BAD_MONTH;
+ gchar *value;
+
+ g_return_val_if_fail (param != NULL, G_DATE_BAD_MONTH);
+
+ value = e_soap_parameter_get_string_value (param);
+ if (!value || !*value) {
+ g_free (value);
+ return G_DATE_BAD_MONTH;
+ }
+
+ /* Do not localize, these are values used in XML */
+ if (g_strcmp0 (value, "January") == 0)
+ month = G_DATE_JANUARY;
+ else if (g_strcmp0 (value, "February") == 0)
+ month = G_DATE_FEBRUARY;
+ else if (g_strcmp0 (value, "March") == 0)
+ month = G_DATE_MARCH;
+ else if (g_strcmp0 (value, "April") == 0)
+ month = G_DATE_APRIL;
+ else if (g_strcmp0 (value, "May") == 0)
+ month = G_DATE_MAY;
+ else if (g_strcmp0 (value, "June") == 0)
+ month = G_DATE_JUNE;
+ else if (g_strcmp0 (value, "July") == 0)
+ month = G_DATE_JULY;
+ else if (g_strcmp0 (value, "August") == 0)
+ month = G_DATE_AUGUST;
+ else if (g_strcmp0 (value, "September") == 0)
+ month = G_DATE_SEPTEMBER;
+ else if (g_strcmp0 (value, "October") == 0)
+ month = G_DATE_OCTOBER;
+ else if (g_strcmp0 (value, "November") == 0)
+ month = G_DATE_NOVEMBER;
+ else if (g_strcmp0 (value, "December") == 0)
+ month = G_DATE_DECEMBER;
+
+ g_free (value);
+
+ return month;
+}
+
+static GDateWeekday
+parse_recur_first_day_of_week (ESoapParameter *param)
+{
+ GDateWeekday first_day_of_week = G_DATE_BAD_WEEKDAY;
+ gchar *value;
+
+ g_return_val_if_fail (param != NULL, G_DATE_BAD_WEEKDAY);
+
+ value = e_soap_parameter_get_string_value (param);
+ if (!value || !*value) {
+ g_free (value);
+ return G_DATE_BAD_WEEKDAY;
+ }
+
+ /* Do not localize, these are values used in XML */
+ if (g_strcmp0 (value, "Sunday") == 0)
+ first_day_of_week = G_DATE_SUNDAY;
+ else if (g_strcmp0 (value, "Monday") == 0)
+ first_day_of_week = G_DATE_MONDAY;
+ else if (g_strcmp0 (value, "Tuesday") == 0)
+ first_day_of_week = G_DATE_TUESDAY;
+ else if (g_strcmp0 (value, "Wednesday") == 0)
+ first_day_of_week = G_DATE_WEDNESDAY;
+ else if (g_strcmp0 (value, "Thursday") == 0)
+ first_day_of_week = G_DATE_THURSDAY;
+ else if (g_strcmp0 (value, "Friday") == 0)
+ first_day_of_week = G_DATE_FRIDAY;
+ else if (g_strcmp0 (value, "Saturday") == 0)
+ first_day_of_week = G_DATE_SATURDAY;
+
+ g_free (value);
+
+ return first_day_of_week;
+}
+
+static void
+parse_recurrence_field (EEwsItem *item,
+ ESoapParameter *param)
+{
+ ESoapParameter *subparam, *subparam1;
+
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (param != NULL);
+
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+
+ if ((subparam = e_soap_parameter_get_first_child_by_name (param, "RelativeYearlyRecurrence")) !=
NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_RELATIVE_YEARLY;
+ item->priv->recurrence.recur.relative_yearly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ item->priv->recurrence.recur.relative_yearly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+ item->priv->recurrence.recur.relative_yearly.month = G_DATE_BAD_MONTH;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DaysOfWeek");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_yearly.days_of_week = parse_recur_days_of_week
(subparam1);
+
+ if (item->priv->recurrence.recur.relative_yearly.days_of_week ==
E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DayOfWeekIndex");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_yearly.day_of_week_index =
parse_recur_day_of_week_index (subparam1);
+
+ if (item->priv->recurrence.recur.relative_yearly.day_of_week_index ==
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Month");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_yearly.month = parse_recur_month (subparam1);
+
+ if (item->priv->recurrence.recur.relative_yearly.month == G_DATE_BAD_MONTH)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "AbsoluteYearlyRecurrence"))
!= NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_ABSOLUTE_YEARLY;
+ item->priv->recurrence.recur.absolute_yearly.day_of_month = 0;
+ item->priv->recurrence.recur.absolute_yearly.month = G_DATE_BAD_MONTH;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DayOfMonth");
+ if (subparam1) {
+ item->priv->recurrence.recur.absolute_yearly.day_of_month =
e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.absolute_yearly.day_of_month < 1 ||
+ item->priv->recurrence.recur.absolute_yearly.day_of_month > 31)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Month");
+ if (subparam1) {
+ item->priv->recurrence.recur.absolute_yearly.month = parse_recur_month (subparam1);
+
+ if (item->priv->recurrence.recur.absolute_yearly.month == G_DATE_BAD_MONTH)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "RelativeMonthlyRecurrence"))
!= NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_RELATIVE_MONTHLY;
+ item->priv->recurrence.recur.relative_monthly.interval = 0;
+ item->priv->recurrence.recur.relative_monthly.days_of_week =
E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ item->priv->recurrence.recur.relative_monthly.day_of_week_index =
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_monthly.interval =
e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.relative_monthly.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DaysOfWeek");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_monthly.days_of_week = parse_recur_days_of_week
(subparam1);
+
+ if (item->priv->recurrence.recur.relative_monthly.days_of_week ==
E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DayOfWeekIndex");
+ if (subparam1) {
+ item->priv->recurrence.recur.relative_monthly.day_of_week_index =
parse_recur_day_of_week_index (subparam1);
+
+ if (item->priv->recurrence.recur.relative_monthly.day_of_week_index ==
E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "AbsoluteMonthlyRecurrence"))
!= NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_ABSOLUTE_MONTHLY;
+ item->priv->recurrence.recur.absolute_monthly.interval = 0;
+ item->priv->recurrence.recur.absolute_monthly.day_of_month = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.absolute_monthly.interval =
e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.absolute_monthly.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DayOfMonth");
+ if (subparam1) {
+ item->priv->recurrence.recur.absolute_monthly.day_of_month =
e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.absolute_monthly.day_of_month < 1 ||
+ item->priv->recurrence.recur.absolute_monthly.day_of_month > 31)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "WeeklyRecurrence")) != NULL)
{
+ item->priv->recurrence.type = E_EWS_RECURRENCE_WEEKLY;
+ item->priv->recurrence.recur.weekly.interval = 0;
+ item->priv->recurrence.recur.weekly.days_of_week = E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN;
+ item->priv->recurrence.recur.weekly.first_day_of_week = G_DATE_BAD_WEEKDAY;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.weekly.interval = e_soap_parameter_get_int_value
(subparam1);
+
+ if (item->priv->recurrence.recur.weekly.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "DaysOfWeek");
+ if (subparam1) {
+ item->priv->recurrence.recur.weekly.days_of_week = parse_recur_days_of_week
(subparam1);
+
+ if (item->priv->recurrence.recur.weekly.days_of_week ==
E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "FirstDayOfWeek");
+ if (subparam1) {
+ item->priv->recurrence.recur.weekly.first_day_of_week = parse_recur_first_day_of_week
(subparam1);
+
+ if (item->priv->recurrence.recur.weekly.first_day_of_week == G_DATE_BAD_WEEKDAY)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ /* It's okay, because 2007 doesn't support it */
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "DailyRecurrence")) != NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_DAILY;
+ item->priv->recurrence.recur.interval = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.interval = e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "DailyRegeneration")) !=
NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_DAILY_REGENERATION;
+ item->priv->recurrence.recur.interval = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.interval = e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "WeeklyRegeneration")) !=
NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_WEEKLY_REGENERATION;
+ item->priv->recurrence.recur.interval = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.interval = e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "MonthlyRegeneration")) !=
NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_MONTHLY_REGENERATION;
+ item->priv->recurrence.recur.interval = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.interval = e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "YearlyRegeneration")) !=
NULL) {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_YEARLY_REGENERATION;
+ item->priv->recurrence.recur.interval = 0;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "Interval");
+ if (subparam1) {
+ item->priv->recurrence.recur.interval = e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.recur.interval < 1)
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ } else {
+ item->priv->recurrence.type = E_EWS_RECURRENCE_UNKNOWN;
+ }
+ }
+
+ if (item->priv->recurrence.type != E_EWS_RECURRENCE_UNKNOWN) {
+ if ((subparam = e_soap_parameter_get_first_child_by_name (param, "NoEndRecurrence")) != NULL)
{
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "StartDate");
+ if (subparam1) {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_NO_END;
+ item->priv->recurrence.utc_start_date = ews_item_parse_date (subparam1);
+
+ if (item->priv->recurrence.utc_start_date == (time_t) -1)
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param, "EndDateRecurrence"))
!= NULL) {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_DATE;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "StartDate");
+ if (subparam1) {
+ item->priv->recurrence.utc_start_date = ews_item_parse_date (subparam1);
+
+ if (item->priv->recurrence.utc_start_date == (time_t) -1)
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ } else {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "EndDate");
+ if (subparam1) {
+ item->priv->recurrence.end.utc_end_date = ews_item_parse_date (subparam1);
+
+ if (item->priv->recurrence.end.utc_end_date == (time_t) -1)
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ } else {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ }
+ } else if ((subparam = e_soap_parameter_get_first_child_by_name (param,
"NumberedRecurrence")) != NULL) {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_NUMBERED;
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam, "StartDate");
+ if (subparam1) {
+ item->priv->recurrence.utc_start_date = ews_item_parse_date (subparam1);
+
+ if (item->priv->recurrence.utc_start_date == (time_t) -1)
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ } else {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ }
+
+ subparam1 = e_soap_parameter_get_first_child_by_name (subparam,
"NumberOfOccurrences");
+ if (subparam1) {
+ item->priv->recurrence.end.number_of_occurrences =
e_soap_parameter_get_int_value (subparam1);
+
+ if (item->priv->recurrence.end.number_of_occurrences < 1)
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ } else {
+ item->priv->recurrence.end_type = E_EWS_RECURRENCE_END_UNKNOWN;
+ }
+ }
+ }
+
+ g_warn_if_fail (
+ (item->priv->recurrence.type == E_EWS_RECURRENCE_UNKNOWN && item->priv->recurrence.end_type
== E_EWS_RECURRENCE_END_UNKNOWN) ||
+ (item->priv->recurrence.type != E_EWS_RECURRENCE_UNKNOWN && item->priv->recurrence.end_type
!= E_EWS_RECURRENCE_END_UNKNOWN));
+}
+
static gchar *
strip_html_tags (const gchar *html_text)
{
@@ -895,20 +1377,13 @@ parse_task_field (EEwsItem *item,
} else if (!g_ascii_strcasecmp (name, "PercentComplete")) {
priv->task_fields->percent_complete = e_soap_parameter_get_string_value (subparam);
} else if (!g_ascii_strcasecmp (name, "DueDate")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->task_fields->due_date = ews_item_parse_date (value);
- g_free (value);
+ priv->task_fields->due_date = ews_item_parse_date (subparam);
priv->task_fields->has_due_date = TRUE;
} else if (!g_ascii_strcasecmp (name, "StartDate")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->task_fields->start_date = ews_item_parse_date (value);
- g_free (value);
+ priv->task_fields->start_date = ews_item_parse_date (subparam);
priv->task_fields->has_start_date = TRUE;
- }
- else if (!g_ascii_strcasecmp (name, "CompleteDate")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->task_fields->complete_date = ews_item_parse_date (value);
- g_free (value);
+ } else if (!g_ascii_strcasecmp (name, "CompleteDate")) {
+ priv->task_fields->complete_date = ews_item_parse_date (subparam);
priv->task_fields->has_complete_date = TRUE;
} else if (!g_ascii_strcasecmp (name, "Sensitivity")) {
priv->task_fields->sensitivity = e_soap_parameter_get_string_value (subparam);
@@ -927,6 +1402,8 @@ parse_task_field (EEwsItem *item,
g_free (priv->task_fields->delegator);
priv->task_fields->delegator = NULL;
}
+ } else if (!g_ascii_strcasecmp (name, "Recurrence")) {
+ parse_recurrence_field (item, subparam);
}
}
@@ -1069,9 +1546,7 @@ e_ews_item_set_from_soap_parameter (EEwsItem *item,
g_free (str);
}
} else if (!g_ascii_strcasecmp (name, "DateTimeReceived")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->date_received = ews_item_parse_date (value);
- g_free (value);
+ priv->date_received = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "Size")) {
priv->size = e_soap_parameter_get_int_value (subparam);
} else if (!g_ascii_strcasecmp (name, "Categories")) {
@@ -1081,13 +1556,9 @@ e_ews_item_set_from_soap_parameter (EEwsItem *item,
} else if (!g_ascii_strcasecmp (name, "InReplyTo")) {
priv->in_replyto = e_soap_parameter_get_string_value (subparam);
} else if (!g_ascii_strcasecmp (name, "DateTimeSent")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->date_sent = ews_item_parse_date (value);
- g_free (value);
+ priv->date_sent = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "DateTimeCreated")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->date_created = ews_item_parse_date (value);
- g_free (value);
+ priv->date_created = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "HasAttachments")) {
value = e_soap_parameter_get_string_value (subparam);
priv->has_attachments = (!g_ascii_strcasecmp (value, "true"));
@@ -1145,9 +1616,7 @@ e_ews_item_set_from_soap_parameter (EEwsItem *item,
priv->reminder_is_set = (!g_ascii_strcasecmp (value, "true"));
g_free (value);
} else if (!g_ascii_strcasecmp (name, "ReminderDueBy")) {
- value = e_soap_parameter_get_string_value (subparam);
- priv->reminder_due_by = ews_item_parse_date (value);
- g_free (value);
+ priv->reminder_due_by = ews_item_parse_date (subparam);
} else if (!g_ascii_strcasecmp (name, "ReminderMinutesBeforeStart")) {
priv->reminder_minutes_before_start = e_soap_parameter_get_int_value (subparam);
} else if (priv->item_type == E_EWS_ITEM_TYPE_TASK || priv->item_type ==
E_EWS_ITEM_TYPE_MEMO) {
@@ -1932,6 +2401,23 @@ e_ews_item_get_reminder_minutes_before_start (EEwsItem *item)
return item->priv->reminder_minutes_before_start;
}
+/* the out_recurrence is filled only if the function returns TRUE */
+gboolean
+e_ews_item_get_recurrence (EEwsItem *item,
+ EEwsRecurrence *out_recurrence)
+{
+ g_return_val_if_fail (E_IS_EWS_ITEM (item), FALSE);
+ g_return_val_if_fail (out_recurrence != NULL, -1);
+
+ if (item->priv->recurrence.type == E_EWS_RECURRENCE_UNKNOWN ||
+ item->priv->recurrence.end_type == E_EWS_RECURRENCE_END_UNKNOWN)
+ return FALSE;
+
+ *out_recurrence = item->priv->recurrence;
+
+ return TRUE;
+}
+
const gchar *
e_ews_item_get_fileas (EEwsItem *item)
{
diff --git a/src/server/e-ews-item.h b/src/server/e-ews-item.h
index a2f3ce1..9c4f8c8 100644
--- a/src/server/e-ews-item.h
+++ b/src/server/e-ews-item.h
@@ -162,6 +162,93 @@ typedef struct {
guint32 rights; /* EEwsPermissionBits for the user */
} EEwsPermission;
+typedef enum {
+ E_EWS_RECURRENCE_UNKNOWN = 0,
+ E_EWS_RECURRENCE_RELATIVE_YEARLY,
+ E_EWS_RECURRENCE_ABSOLUTE_YEARLY,
+ E_EWS_RECURRENCE_RELATIVE_MONTHLY,
+ E_EWS_RECURRENCE_ABSOLUTE_MONTHLY,
+ E_EWS_RECURRENCE_WEEKLY,
+ E_EWS_RECURRENCE_DAILY,
+ E_EWS_RECURRENCE_DAILY_REGENERATION,
+ E_EWS_RECURRENCE_WEEKLY_REGENERATION,
+ E_EWS_RECURRENCE_MONTHLY_REGENERATION,
+ E_EWS_RECURRENCE_YEARLY_REGENERATION
+} EEwsRecurrenceType;
+
+typedef enum {
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_UNKNOWN = 0,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_SUNDAY = 1 << 0,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_MONDAY = 1 << 1,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_TUESDAY = 1 << 2,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_WEDNESDAY = 1 << 3,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_THURSDAY = 1 << 4,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_FRIDAY = 1 << 5,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_SATURDAY = 1 << 6,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_DAY = 1 << 7,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKDAY = 1 << 8,
+ E_EWS_RECURRENCE_DAYS_OF_WEEK_WEEKENDDAY = 1 << 9
+} EEwsRecurrenceDaysOfWeek;
+
+typedef enum {
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_UNKNOWN = 0,
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FIRST,
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_SECOND,
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_THIRD,
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_FOURTH,
+ E_EWS_RECURRENCE_DAY_OF_WEEK_INDEX_LAST
+} EEwsRecurrenceDayOfWeekIndex;
+
+typedef enum {
+ E_EWS_RECURRENCE_END_UNKNOWN = 0,
+ E_EWS_RECURRENCE_END_NO_END,
+ E_EWS_RECURRENCE_END_DATE,
+ E_EWS_RECURRENCE_END_NUMBERED
+} EEwsRecurrenceEndType;
+
+typedef struct {
+ EEwsRecurrenceType type;
+ union _recur {
+ struct _relative_yearly {
+ guint32 days_of_week; /* bit-or of EEwsRecurrenceDaysOfWeek */
+ EEwsRecurrenceDayOfWeekIndex day_of_week_index;
+ GDateMonth month; /* 1..12 */
+ } relative_yearly;
+
+ struct _absolute_yearly {
+ gint day_of_month; /* 1..31 */
+ GDateMonth month; /* 1..12 */
+ } absolute_yearly;
+
+ struct _relative_monthly {
+ gint interval; /* 1..99 */
+ guint32 days_of_week; /* bit-or of EEwsRecurrenceDaysOfWeek */
+ EEwsRecurrenceDayOfWeekIndex day_of_week_index;
+ } relative_monthly;
+
+ struct _absolute_monthly {
+ gint interval; /* 1..99 */
+ gint day_of_month; /* 1..31 */
+ } absolute_monthly;
+
+ struct _weekly {
+ gint interval; /* 1..99 */
+ guint32 days_of_week; /* bit-or of EEwsRecurrenceDaysOfWeek */
+ GDateWeekday first_day_of_week; /* Exchange 2013 server and above */
+ } weekly;
+
+ /* Used for daily, daily_regeneration, weekly_regeneration, monthly_regeneration and
yearly_regeneration */
+ gint interval; /* 1..999 */
+ } recur;
+
+ EEwsRecurrenceEndType end_type;
+ time_t utc_start_date;
+ union _end {
+ time_t utc_end_date;
+ gint number_of_occurrences;
+ } end;
+} EEwsRecurrence;
+
GType e_ews_item_get_type (void);
EEwsItem * e_ews_item_new_from_soap_parameter
(ESoapParameter *param);
@@ -214,6 +301,8 @@ gboolean e_ews_item_get_reminder_is_set (EEwsItem *item);
time_t e_ews_item_get_reminder_due_by (EEwsItem *item);
gint e_ews_item_get_reminder_minutes_before_start
(EEwsItem *item);
+gboolean e_ews_item_get_recurrence (EEwsItem *item,
+ EEwsRecurrence *out_recurrence);
EwsMailbox *
e_ews_item_mailbox_from_soap_param
(ESoapParameter *param);
diff --git a/tests/ews-test-timezones.c b/tests/ews-test-timezones.c
index 1ac64b1..7f18173 100644
--- a/tests/ews-test-timezones.c
+++ b/tests/ews-test-timezones.c
@@ -26,7 +26,7 @@
void (* populate_windows_zones) (void);
const gchar * (* ical_to_msdn_equivalent) (const gchar *);
-void (* convert_calcomp_to_xml) (ESoapMessage *, gpointer);
+gboolean (* convert_calcomp_to_xml) (ESoapMessage *, gpointer, GError **);
const gchar *str_comp =
"BEGIN:VEVENT\n"
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]