[evolution-ews] Bug #712179 - Cannot create calendar object: The property is deprecated for this version of Exchange
- From: Fabiano Fidêncio <ffidencio src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Bug #712179 - Cannot create calendar object: The property is deprecated for this version of Exchange
- Date: Fri, 17 Jan 2014 13:48:20 +0000 (UTC)
commit c753d99bb3bb4acc60f08eb49f59ae67b77dc832
Author: Fabiano Fidêncio <fidencio redhat com>
Date: Wed Nov 13 20:20:19 2013 +0100
Bug #712179 - Cannot create calendar object: The property is deprecated for this version of Exchange.
src/calendar/e-cal-backend-ews-utils.c | 1752 +++++++++++++++++++++++++++++++-
src/calendar/e-cal-backend-ews-utils.h | 43 +-
src/calendar/e-cal-backend-ews.c | 1688 ++++++++----------------------
src/calendar/e-cal-backend-ews.h | 9 +
src/server/e-ews-connection.c | 797 +++++++++++++++
src/server/e-ews-connection.h | 175 ++++
src/server/e-ews-item.c | 5 +
7 files changed, 3224 insertions(+), 1245 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index 1add02c..0a66558 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -39,10 +39,668 @@
#include "server/e-ews-connection.h"
#include "server/e-ews-message.h"
+#include "server/e-ews-item-change.h"
#include "e-cal-backend-ews-utils.h"
/*
+ * A bunch of global variables used to map the icaltimezone to MSDN[0] format.
+ * Also, some auxiliar functions to translate from one tz type to another.
+ *
+ * [0]: http://msdn.microsoft.com/en-us/library/ms912391(v=winembedded.11).aspx
+ */
+static GRecMutex tz_mutex;
+
+static GHashTable *ical_to_msdn = NULL;
+static GHashTable *msdn_to_ical = NULL;
+
+struct tz_map {
+ const gchar *from;
+ const gchar *to;
+};
+
+static const struct tz_map msdn_to_ical_table[] = {
+ { "Dateline Standard Time", "Pacific/Apia" },
+ { "Samoa Standard Time", "Pacific/Midway" },
+ { "Hawaiian Standard Time", "Pacific/Honolulu" },
+ { "Alaskan Standard Time", "America/Anchorage" },
+ { "Pacific Standard Time", "America/Los_Angeles" },
+ { "Pacific Standard Time (Mexico)", "America/Tijuana" },
+ { "US Mountain Standard Time", "America/Phoenix" },
+ { "Mountain Standard Time (Mexico)", "America/Mazatlan" },
+ { "Mexico Standard Time 2", "America/Chihuahua" },
+ { "Mountain Standard Time", "America/Denver" },
+ { "Central America Standard Time", "America/Costa_Rica" },
+ { "Central Standard Time", "America/Chicago" },
+ { "Central Standard Time (Mexico)", "America/Monterrey" },
+ { "Mexico Standard Time", "America/Mexico_City" },
+ { "Canada Central Standard Time", "America/Winnipeg" },
+ { "SA Pacific Standard Time", "America/Bogota" },
+ { "Eastern Standard Time", "America/New_York" },
+ { "US Eastern Standard Time", "America/Indiana/Indianapolis" },
+ { "Venezuela Standard Time", "America/Caracas" },
+ { "Atlantic Standard Time", "America/Halifax" },
+ { "SA Western Standard Time", "America/La_Paz" },
+ { "Central Brazilian Standard Time", "America/Manaus" },
+ { "Pacific SA Standard Time", "America/La_Paz" },
+ { "Newfoundland Standard Time", "America/St_Johns" },
+ { "E. South America Standard Time", "America/Bahia" },
+ { "SA Eastern Standard Time", "America/Argentina/Buenos_Aires" },
+ { "Greenland Standard Time", "America/Godthab" },
+ { "Montevideo Standard Time", "America/Montevideo" },
+ { "Mid-Atlantic Standard Time", "Atlantic/South_Georgia" },
+ { "Azores Standard Time", "Atlantic/Azores" },
+ { "Cape Verde Standard Time", "Atlantic/Cape_Verde" },
+ { "Greenwich Standard Time", "Africa/Casablanca" },
+ { "GMT Standard Time", "Europe/Dublin" },
+ { "UTC", "UTC" },
+ { "W. Europe Standard Time", "Europe/Berlin" },
+ { "Central Europe Standard Time", "Europe/Prague" },
+ { "Romance Standard Time", "Europe/Paris" },
+ { "Central European Standard Time", "Europe/Belgrade" },
+ { "W. Central Africa Standard Time", "Africa/Luanda" },
+ { "Jordan Standard Time", "Asia/Amman" },
+ { "GTB Standard Time", "Europe/Athens" },
+ { "Middle East Standard Time", "Asia/Beirut" },
+ { "Egypt Standard Time", "Africa/Cairo" },
+ { "South Africa Standard Time", "Africa/Harare" },
+ { "FLE Standard Time", "Europe/Helsinki" },
+ { "Israel Standard Time", "Asia/Jerusalem" },
+ { "E. Europe Standard Time", "Europe/Minsk" },
+ { "Namibia Standard Time", "Africa/Windhoek" },
+ { "Arabic Standard Time", "Asia/Baghdad" },
+ { "Arab Standard Time", "Asia/Qatar" },
+ { "Russian Standard Time", "Europe/Moscow" },
+ { "E. Africa Standard Time", "Africa/Nairobi" },
+ { "Georgian Standard Time", "Asia/Tbilisi" },
+ { "Iran Standard Time", "Asia/Tehran" },
+ { "Arabian Standard Time", "Asia/Muscat" },
+ { "Azerbaijan Standard Time", "Asia/Baku" },
+ { "Caucasus Standard Time", "Asia/Yerevan" },
+ { "Armenian Standard Time", "Asia/Yerevan" },
+ { "Afghanistan Standard Time", "Asia/Kabul" },
+ { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" },
+ { "West Asia Standard Time", "Asia/Karachi" },
+ { "India Standard Time", "Asia/Kolkata" },
+ { "Sri Lanka Standard Time", "Asia/Colombo" },
+ { "Nepal Standard Time", "Asia/Kathmandu" },
+ { "N. Central Asia Standard Time", "Asia/Novosibirsk" },
+ { "Central Asia Standard Time", "Asia/Dhaka" },
+ { "Myanmar Standard Time", "Asia/Rangoon" },
+ { "SE Asia Standard Time", "Asia/Bangkok" },
+ { "North Asia Standard Time", "Asia/Krasnoyarsk" },
+ { "China Standard Time", "Asia/Shanghai" },
+ { "North Asia East Standard Time", "Asia/Ulaanbaatar" },
+ { "Singapore Standard Time", "Asia/Singapore" },
+ { "W. Australia Standard Time", "Australia/Perth" },
+ { "Taipei Standard Time", "Asia/Taipei" },
+ { "Tokyo Standard Time", "Asia/Tokyo" },
+ { "Korea Standard Time", "Asia/Seoul" },
+ { "Yakutsk Standard Time", "Asia/Yakutsk" },
+ { "Cen. Australia Standard Time", "Australia/Adelaide" },
+ { "AUS Central Standard Time", "Australia/Darwin" },
+ { "E. Australia Standard Time", "Australia/Brisbane" },
+ { "AUS Eastern Standard Time", "Australia/Sydney" },
+ { "West Pacific Standard Time", "Pacific/Guam" },
+ { "Tasmania Standard Time", "Australia/Hobart" },
+ { "Vladivostok Standard Time", "Asia/Vladivostok" },
+ { "Central Pacific Standard Time", "Asia/Magadan" },
+ { "New Zealand Standard Time", "Pacific/Auckland" },
+ { "Fiji Standard Time", "Pacific/Fiji" },
+ { "Tonga Standard Time", "Pacific/Tongatapu" },
+};
+
+static const struct tz_map ical_to_msdn_table[] = {
+ { "UTC", "UTC" },
+ { "Africa/Abidjan", "Greenwich Standard Time" },
+ { "Africa/Accra", "Greenwich Standard Time" },
+ { "Africa/Addis_Ababa", "E. Africa Standard Time" },
+ { "Africa/Algiers", "W. Central Africa Standard Time" },
+ { "Africa/Asmara", "E. Africa Standard Time" },
+ { "Africa/Bamako", "Greenwich Standard Time" },
+ { "Africa/Bangui", "W. Central Africa Standard Time" },
+ { "Africa/Banjul", "Greenwich Standard Time" },
+ { "Africa/Bissau", "Greenwich Standard Time" },
+ { "Africa/Blantyre", "South Africa Standard Time" },
+ { "Africa/Brazzaville", "W. Central Africa Standard Time" },
+ { "Africa/Bujumbura", "South Africa Standard Time" },
+ { "Africa/Cairo", "Egypt Standard Time" },
+ { "Africa/Casablanca", "Greenwich Standard Time" },
+ { "Africa/Ceuta", "W. Central Africa Standard Time" },
+ { "Africa/Conakry", "Greenwich Standard Time" },
+ { "Africa/Dakar", "Greenwich Standard Time" },
+ { "Africa/Dar_es_Salaam", "E. Africa Standard Time" },
+ { "Africa/Djibouti", "E. Africa Standard Time" },
+ { "Africa/Douala", "W. Central Africa Standard Time" },
+ { "Africa/El_Aaiun", "Greenwich Standard Time" },
+ { "Africa/Freetown", "Greenwich Standard Time" },
+ { "Africa/Gaborone", "South Africa Standard Time" },
+ { "Africa/Harare", "South Africa Standard Time" },
+ { "Africa/Johannesburg", "South Africa Standard Time" },
+ { "Africa/Juba", "E. Africa Standard Time" },
+ { "Africa/Kampala", "E. Africa Standard Time" },
+ { "Africa/Khartoum", "E. Africa Standard Time" },
+ { "Africa/Kigali", "Egypt Standard Time" },
+ { "Africa/Kinshasa", "W. Central Africa Standard Time" },
+ { "Africa/Lagos", "Greenwich Standard Time" },
+ { "Africa/Libreville", "W. Central Africa Standard Time" },
+ { "Africa/Lome", "Greenwich Standard Time" },
+ { "Africa/Luanda", "W. Central Africa Standard Time" },
+ { "Africa/Lubumbashi", "South Africa Standard Time" },
+ { "Africa/Lusaka", "South Africa Standard Time" },
+ { "Africa/Malabo", "W. Central Africa Standard Time" },
+ { "Africa/Maputo", "South Africa Standard Time" },
+ { "Africa/Maseru", "South Africa Standard Time" },
+ { "Africa/Mbabane", "South Africa Standard Time" },
+ { "Africa/Mogadishu", "E. Africa Standard Time" },
+ { "Africa/Monrovia", "Greenwich Standard Time" },
+ { "Africa/Nairobi", "E. Africa Standard Time" },
+ { "Africa/Ndjamena", "W. Central Africa Standard Time" },
+ { "Africa/Niamey", "W. Central Africa Standard Time" },
+ { "Africa/Nouakchott", "Greenwich Standard Time" },
+ { "Africa/Ouagadougou", "Greenwich Standard Time" },
+ { "Africa/Porto-Novo", "W. Central Africa Standard Time" },
+ { "Africa/Sao_Tome", "Cape Verde Standard Time" },
+ { "Africa/Tripoli", "Egypt Standard Time" },
+ { "Africa/Tunis", "W. Central Africa Standard Time" },
+ { "Africa/Windhoek", "Namibia Standard Time" },
+ { "America/Adak", "Hawaiian Standard Time" },
+ { "America/Anchorage", "Alaskan Standard Time" },
+ { "America/Anguilla", "SA Western Standard Time" },
+ { "America/Antigua", "SA Western Standard Time" },
+ { "America/Araguaina", "E. South America Standard Time" },
+ { "America/Argentina/Buenos_Aires", "SA Eastern Standard Time" },
+ { "America/Argentina/Catamarca", "SA Eastern Standard Time" },
+ { "America/Argentina/Cordoba", "SA Eastern Standard Time" },
+ { "America/Argentina/Jujuy", "SA Eastern Standard Time" },
+ { "America/Argentina/La_Rioja", "SA Eastern Standard Time" },
+ { "America/Argentina/Mendoza", "SA Eastern Standard Time" },
+ { "America/Argentina/Rio_Gallegos", "SA Eastern Standard Time" },
+ { "America/Argentina/Salta", "SA Eastern Standard Time" },
+ { "America/Argentina/San_Luis", "SA Eastern Standard Time" },
+ { "America/Argentina/San_Juan", "SA Eastern Standard Time" },
+ { "America/Argentina/Tucuman", "SA Eastern Standard Time" },
+ { "America/Argentina/Ushuaia", "SA Eastern Standard Time" },
+ { "America/Aruba", "Venezuela Standard Time" },
+ { "America/Asuncion", "SA Eastern Standard Time" },
+ { "America/Atikokan", "US Eastern Standard Time" },
+ { "America/Bahia", "E. South America Standard Time" },
+ { "America/Bahia_Banderas", "Central Standard Time (Mexico)" },
+ { "America/Barbados", "SA Western Standard Time" },
+ { "America/Belem", "E. South America Standard Time" },
+ { "America/Belize", "Mexico Standard Time" },
+ { "America/Blanc-Sablon", "Atlantic Standard Time" },
+ { "America/Boa_Vista", "SA Western Standard Time" },
+ { "America/Bogota", "SA Pacific Standard Time" },
+ { "America/Boise", "US Mountain Standard Time" },
+ { "America/Cambridge_Bay", "Mountain Standard Time" },
+ { "America/Campo_Grande", "E. South America Standard Time" },
+ { "America/Cancun", "Central America Standard Time" },
+ { "America/Caracas", "Venezuela Standard Time" },
+ { "America/Cayenne", "E. South America Standard Time" },
+ { "America/Cayman", "SA Pacific Standard Time" },
+ { "America/Chicago", "Central Standard Time" },
+ { "America/Chihuahua", "Mexico Standard Time 2" },
+ { "America/Costa_Rica", "Central America Standard Time" },
+ { "America/Creston", "Mountain Standard Time" },
+ { "America/Cuiaba", "E. South America Standard Time" },
+ { "America/Curacao", "Venezuela Standard Time" },
+ { "America/Danmarkshavn", "GMT Standard Time" },
+ { "America/Dawson", "Pacific Standard Time" },
+ { "America/Dawson_Creek", "Mountain Standard Time" },
+ { "America/Denver", "Mountain Standard Time" },
+ { "America/Detroit", "Eastern Standard Time" },
+ { "America/Dominica", "SA Western Standard Time" },
+ { "America/Edmonton", "Mountain Standard Time" },
+ { "America/Eirunepe", "SA Pacific Standard Time" },
+ { "America/El_Salvador", "Central America Standard Time" },
+ { "America/Fortaleza", "E. South America Standard Time" },
+ { "America/Glace_Bay", "Atlantic Standard Time" },
+ { "America/Godthab", "Greenland Standard Time" },
+ { "America/Goose_Bay", "Atlantic Standard Time" },
+ { "America/Grand_Turk", "SA Pacific Standard Time" },
+ { "America/Grenada", "SA Western Standard Time" },
+ { "America/Guadeloupe", "SA Western Standard Time" },
+ { "America/Guatemala", "Central America Standard Time" },
+ { "America/Guayaquil", "SA Pacific Standard Time" },
+ { "America/Guyana", "Venezuela Standard Time" },
+ { "America/Halifax", "Atlantic Standard Time" },
+ { "America/Havana", "SA Pacific Standard Time" },
+ { "America/Hermosillo", "Mexico Standard Time 2" },
+ { "America/Indiana/Indianapolis", "US Eastern Standard Time" },
+ { "America/Indiana/Knox", "Canada Central Standard Time" },
+ { "America/Indiana/Marengo", "US Eastern Standard Time" },
+ { "America/Indiana/Petersburg", "US Eastern Standard Time" },
+ { "America/Indiana/Tell_City", "Canada Central Standard Time" },
+ { "America/Indiana/Vevay", "US Eastern Standard Time" },
+ { "America/Indiana/Vincennes", "US Eastern Standard Time" },
+ { "America/Indiana/Winamac", "US Eastern Standard Time" },
+ { "America/Inuvik", "Mountain Standard Time" },
+ { "America/Iqaluit", "Eastern Standard Time" },
+ { "America/Jamaica", "SA Pacific Standard Time" },
+ { "America/Juneau", "Alaskan Standard Time" },
+ { "America/Kentucky/Louisville", "US Eastern Standard Time" },
+ { "America/Kentucky/Monticello", "US Eastern Standard Time" },
+ { "America/Kralendijk", "Venezuela Standard Time" },
+ { "America/La_Paz", "SA Western Standard Time" },
+ { "America/Lima", "SA Pacific Standard Time" },
+ { "America/Los_Angeles", "Pacific Standard Time" },
+ { "America/Lower_Princes", "Venezuela Standard Time" },
+ { "America/Maceio", "E. South America Standard Time" },
+ { "America/Managua", "Central America Standard Time" },
+ { "America/Manaus", "Central Brazilian Standard Time" },
+ { "America/Marigot", "SA Western Standard Time" },
+ { "America/Martinique", "SA Western Standard Time" },
+ { "America/Matamoros", "Central Standard Time" },
+ { "America/Mazatlan", "Mountain Standard Time (Mexico)" },
+ { "America/Menominee", "Central Standard Time" },
+ { "America/Merida", "Central America Standard Time" },
+ { "America/Metlakatla", "Alaskan Standard Time" },
+ { "America/Mexico_City", "Mexico Standard Time" },
+ { "America/Miquelon", "Greenland Standard Time" },
+ { "America/Moncton", "Atlantic Standard Time" },
+ { "America/Monterrey", "Central Standard Time (Mexico)" },
+ { "America/Montevideo", "Montevideo Standard Time" },
+ { "America/Montreal", "Eastern Standard Time" },
+ { "America/Montserrat", "SA Western Standard Time" },
+ { "America/Nassau", "Eastern Standard Time" },
+ { "America/New_York", "Eastern Standard Time" },
+ { "America/Nipigon", "Eastern Standard Time" },
+ { "America/Nome", "Alaskan Standard Time" },
+ { "America/Noronha", "Mid-Atlantic Standard Time" },
+ { "America/North_Dakota/Beulah", "Central Standard Time" },
+ { "America/North_Dakota/Center", "Central Standard Time" },
+ { "America/North_Dakota/New_Salem", "Central Standard Time" },
+ { "America/Ojinaga", "Mexico Standard Time 2" },
+ { "America/Panama", "SA Pacific Standard Time" },
+ { "America/Pangnirtung", "Eastern Standard Time" },
+ { "America/Paramaribo", "Venezuela Standard Time" },
+ { "America/Phoenix", "US Mountain Standard Time" },
+ { "America/Port-au-Prince", "SA Western Standard Time" },
+ { "America/Port_of_Spain", "SA Western Standard Time" },
+ { "America/Porto_Velho", "SA Western Standard Time" },
+ { "America/Puerto_Rico", "SA Western Standard Time" },
+ { "America/Rainy_River", "Canada Central Standard Time" },
+ { "America/Rankin_Inlet", "Canada Central Standard Time" },
+ { "America/Recife", "E. South America Standard Time" },
+ { "America/Regina", "Central America Standard Time" },
+ { "America/Resolute", "Eastern Standard Time" },
+ { "America/Rio_Branco", "SA Pacific Standard Time" },
+ { "America/Santa_Isabel", "Pacific Standard Time (Mexico)" },
+ { "America/Santarem", "E. South America Standard Time" },
+ { "America/Santiago", "Pacific SA Standard Time" },
+ { "America/Santo_Domingo", "SA Western Standard Time" },
+ { "America/Sao_Paulo", "Mid-Atlantic Standard Time" },
+ { "America/Scoresbysund", "Azores Standard Time" },
+ { "America/Shiprock", "US Mountain Standard Time" },
+ { "America/Sitka", "Alaskan Standard Time" },
+ { "America/St_Barthelemy", "SA Western Standard Time" },
+ { "America/St_Johns", "Newfoundland Standard Time" },
+ { "America/St_Kitts", "SA Western Standard Time" },
+ { "America/St_Lucia", "SA Western Standard Time" },
+ { "America/St_Thomas", "SA Western Standard Time" },
+ { "America/St_Vincent", "SA Western Standard Time" },
+ { "America/Swift_Current", "Central Standard Time" },
+ { "America/Tegucigalpa", "Central America Standard Time" },
+ { "America/Thule", "Atlantic Standard Time" },
+ { "America/Thunder_Bay", "Eastern Standard Time" },
+ { "America/Tijuana", "Pacific Standard Time (Mexico)" },
+ { "America/Toronto", "Eastern Standard Time" },
+ { "America/Tortola", "SA Western Standard Time" },
+ { "America/Vancouver", "Pacific Standard Time" },
+ { "America/Whitehorse", "Pacific Standard Time" },
+ { "America/Winnipeg", "Canada Central Standard Time" },
+ { "America/Yakutat", "Alaskan Standard Time" },
+ { "America/Yellowknife", "Mountain Standard Time" },
+ { "Antarctica/Casey", "GMT Standard Time" },
+ { "Antarctica/Davis", "SE Asia Standard Time" },
+ { "Antarctica/DumontDUrville", "West Pacific Standard Time" },
+ { "Antarctica/Macquarie", "Central Pacific Standard Time" },
+ { "Antarctica/Mawson", "GMT Standard Time" },
+ { "Antarctica/McMurdo", "Tonga Standard Time" },
+ { "Antarctica/Palmer", "Greenland Standard Time" },
+ { "Antarctica/Rothera", "GMT Standard Time" },
+ { "Antarctica/South_Pole", "GMT Standard Time" },
+ { "Antarctica/Syowa", "GMT Standard Time" },
+ { "Antarctica/Vostok", "GMT Standard Time" },
+ { "Arctic/Longyearbyen", "Central Europe Standard Time" },
+ { "Asia/Aden", "Arab Standard Time" },
+ { "Asia/Almaty", "N. Central Asia Standard Time" },
+ { "Asia/Amman", "Jordan Standard Time" },
+ { "Asia/Anadyr", "Fiji Standard Time" },
+ { "Asia/Aqtau", "Ekaterinburg Standard Time" },
+ { "Asia/Aqtobe", "Ekaterinburg Standard Time" },
+ { "Asia/Ashgabat", "Ekaterinburg Standard Time" },
+ { "Asia/Baghdad", "Arabic Standard Time" },
+ { "Asia/Bahrain", "Arab Standard Time" },
+ { "Asia/Baku", "Azerbaijan Standard Time" },
+ { "Asia/Bangkok", "SE Asia Standard Time" },
+ { "Asia/Beijing", "China Standard Time" },
+ { "Asia/Beirut", "Middle East Standard Time" },
+ { "Asia/Bishkek", "Central Asia Standard Time" },
+ { "Asia/Brunei", "Taipei Standard Time" },
+ { "Asia/Kolkata", "India Standard Time" },
+ { "Asia/Choibalsan", "Yakutsk Standard Time" },
+ { "Asia/Chongqing", "China Standard Time" },
+ { "Asia/Colombo", "India Standard Time" },
+ { "Asia/Damascus", "Israel Standard Time" },
+ { "Asia/Dhaka", "Central Asia Standard Time" },
+ { "Asia/Dili", "Yakutsk Standard Time" },
+ { "Asia/Dubai", "Iran Standard Time" },
+ { "Asia/Dushanbe", "West Asia Standard Time" },
+ { "Asia/Gaza", "Israel Standard Time" },
+ { "Asia/Harbin", "China Standard Time" },
+ { "Asia/Hebron", "Israel Standard Time" },
+ { "Asia/Ho_Chi_Minh", "North Asia Standard Time" },
+ { "Asia/Hong_Kong", "China Standard Time" },
+ { "Asia/Hovd", "North Asia Standard Time" },
+ { "Asia/Irkutsk", "North Asia East Standard Time" },
+ { "Asia/Jakarta", "SE Asia Standard Time" },
+ { "Asia/Jayapura", "Yakutsk Standard Time" },
+ { "Asia/Jerusalem", "Israel Standard Time" },
+ { "Asia/Kabul", "Afghanistan Standard Time" },
+ { "Asia/Kamchatka", "Fiji Standard Time" },
+ { "Asia/Karachi", "West Asia Standard Time" },
+ { "Asia/Kashgar", "China Standard Time" },
+ { "Asia/Kathmandu", "Nepal Standard Time" },
+ { "Asia/Khandyga", "Yakutsk Standard Time" },
+ { "Asia/Krasnoyarsk", "North Asia Standard Time" },
+ { "Asia/Kuala_Lumpur", "Singapore Standard Time" },
+ { "Asia/Kuching", "Taipei Standard Time" },
+ { "Asia/Kuwait", "Arab Standard Time" },
+ { "Asia/Macau", "China Standard Time" },
+ { "Asia/Magadan", "Central Pacific Standard Time" },
+ { "Asia/Makassar", "Taipei Standard Time" },
+ { "Asia/Manila", "Taipei Standard Time" },
+ { "Asia/Muscat", "Arabian Standard Time" },
+ { "Asia/Nicosia", "Israel Standard Time" },
+ { "Asia/Novokuznetsk", "N. Central Asia Standard Time" },
+ { "Asia/Novosibirsk", "N. Central Asia Standard Time" },
+ { "Asia/Omsk", "N. Central Asia Standard Time" },
+ { "Asia/Oral", "Ekaterinburg Standard Time" },
+ { "Asia/Phnom_Penh", "SE Asia Standard Time" },
+ { "Asia/Pontianak", "SE Asia Standard Time" },
+ { "Asia/Pyongyang", "Korea Standard Time" },
+ { "Asia/Qatar", "Arab Standard Time" },
+ { "Asia/Qyzylorda", "Central Asia Standard Time" },
+ { "Asia/Rangoon", "Myanmar Standard Time" },
+ { "Asia/Riyadh", "Arab Standard Time" },
+ { "Asia/Saigon", "SE Asia Standard Time" },
+ { "Asia/Sakhalin", "Vladivostok Standard Time" },
+ { "Asia/Samarkand", "West Asia Standard Time" },
+ { "Asia/Seoul", "Korea Standard Time" },
+ { "Asia/Shanghai", "China Standard Time" },
+ { "Asia/Singapore", "Singapore Standard Time" },
+ { "Asia/Taipei", "Taipei Standard Time" },
+ { "Asia/Tashkent", "West Asia Standard Time" },
+ { "Asia/Tbilisi", "Georgian Standard Time" },
+ { "Asia/Tehran", "Iran Standard Time" },
+ { "Asia/Thimphu", "Central Asia Standard Time" },
+ { "Asia/Tokyo", "Tokyo Standard Time" },
+ { "Asia/Ulaanbaatar", "North Asia East Standard Time" },
+ { "Asia/Ust-Nera", "Yakutsk Standard Time" },
+ { "Asia/Urumqi", "China Standard Time" },
+ { "Asia/Vientiane", "SE Asia Standard Time" },
+ { "Asia/Vladivostok", "Vladivostok Standard Time" },
+ { "Asia/Yakutsk", "Yakutsk Standard Time" },
+ { "Asia/Yekaterinburg", "Ekaterinburg Standard Time" },
+ { "Asia/Yerevan", "Armenian Standard Time" },
+ { "Atlantic/Azores", "Azores Standard Time" },
+ { "Atlantic/Bermuda", "Atlantic Standard Time" },
+ { "Atlantic/Canary", "GMT Standard Time" },
+ { "Atlantic/Cape_Verde", "Cape Verde Standard Time" },
+ { "Atlantic/Faroe", "GMT Standard Time" },
+ { "Atlantic/Jan_Mayen", "W. Europe Standard Time" },
+ { "Atlantic/Madeira", "GMT Standard Time" },
+ { "Atlantic/Reykjavik", "GMT Standard Time" },
+ { "Atlantic/South_Georgia", "Mid-Atlantic Standard Time" },
+ { "Atlantic/Stanley", "SA Eastern Standard Time" },
+ { "Atlantic/St_Helena", "Greenwich Standard Time" },
+ { "Australia/Adelaide", "Cen. Australia Standard Time" },
+ { "Australia/Brisbane", "E. Australia Standard Time" },
+ { "Australia/Broken_Hill", "Cen. Australia Standard Time" },
+ { "Australia/Currie", "AUS Eastern Standard Time" },
+ { "Australia/Darwin", "AUS Central Standard Time" },
+ { "Australia/Eucla", "AUS Central Standard Time" },
+ { "Australia/Hobart", "Tasmania Standard Time" },
+ { "Australia/Lindeman", "E. Australia Standard Time" },
+ { "Australia/Lord_Howe", "AUS Eastern Standard Time" },
+ { "Australia/Melbourne", "AUS Eastern Standard Time" },
+ { "Australia/Perth", "W. Australia Standard Time" },
+ { "Australia/Sydney", "AUS Eastern Standard Time" },
+ { "Europe/Amsterdam", "W. Europe Standard Time" },
+ { "Europe/Andorra", "W. Europe Standard Time" },
+ { "Europe/Athens", "GTB Standard Time" },
+ { "Europe/Belgrade", "Central European Standard Time" },
+ { "Europe/Berlin", "W. Europe Standard Time" },
+ { "Europe/Bratislava", "Central Europe Standard Time" },
+ { "Europe/Brussels", "Romance Standard Time" },
+ { "Europe/Bucharest", "E. Europe Standard Time" },
+ { "Europe/Budapest", "Central Europe Standard Time" },
+ { "Europe/Busingen", "W. Europe Standard Time" },
+ { "Europe/Chisinau", "FLE Standard Time" },
+ { "Europe/Copenhagen", "Romance Standard Time" },
+ { "Europe/Dublin", "GMT Standard Time" },
+ { "Europe/Gibraltar", "Romance Standard Time" },
+ { "Europe/Guernsey", "GMT Standard Time" },
+ { "Europe/Helsinki", "FLE Standard Time" },
+ { "Europe/Isle_of_Man", "GMT Standard Time" },
+ { "Europe/Istanbul", "GTB Standard Time" },
+ { "Europe/Jersey", "GMT Standard Time" },
+ { "Europe/Kaliningrad", "FLE Standard Time" },
+ { "Europe/Kiev", "FLE Standard Time" },
+ { "Europe/Lisbon", "GMT Standard Time" },
+ { "Europe/Ljubljana", "Central Europe Standard Time" },
+ { "Europe/London", "GMT Standard Time" },
+ { "Europe/Luxembourg", "Romance Standard Time" },
+ { "Europe/Madrid", "Romance Standard Time" },
+ { "Europe/Malta", "W. Europe Standard Time" },
+ { "Europe/Mariehamn", "FLE Standard Time" },
+ { "Europe/Minsk", "E. Europe Standard Time" },
+ { "Europe/Monaco", "W. Europe Standard Time" },
+ { "Europe/Moscow", "Russian Standard Time" },
+ { "Europe/Oslo", "W. Europe Standard Time" },
+ { "Europe/Paris", "Romance Standard Time" },
+ { "Europe/Podgorica", "Central European Standard Time" },
+ { "Europe/Prague", "Central Europe Standard Time" },
+ { "Europe/Riga", "FLE Standard Time" },
+ { "Europe/Rome", "W. Europe Standard Time" },
+ { "Europe/Samara", "Caucasus Standard Time" },
+ { "Europe/San_Marino", "W. Europe Standard Time" },
+ { "Europe/Sarajevo", "Central European Standard Time" },
+ { "Europe/Simferopol", "FLE Standard Time" },
+ { "Europe/Skopje", "Central European Standard Time" },
+ { "Europe/Sofia", "FLE Standard Time" },
+ { "Europe/Stockholm", "W. Europe Standard Time" },
+ { "Europe/Tallinn", "FLE Standard Time" },
+ { "Europe/Tirane", "Central European Standard Time" },
+ { "Europe/Uzhgorod", "FLE Standard Time" },
+ { "Europe/Vaduz", "W. Europe Standard Time" },
+ { "Europe/Vatican", "W. Europe Standard Time" },
+ { "Europe/Vienna", "W. Europe Standard Time" },
+ { "Europe/Vilnius", "FLE Standard Time" },
+ { "Europe/Volgograd", "Russian Standard Time" },
+ { "Europe/Warsaw", "Central European Standard Time" },
+ { "Europe/Zagreb", "Central European Standard Time" },
+ { "Europe/Zaporozhye", "FLE Standard Time" },
+ { "Europe/Zurich", "W. Europe Standard Time" },
+ { "Indian/Antananarivo", "E. Africa Standard Time" },
+ { "Indian/Chagos", "Sri Lanka Standard Time" },
+ { "Indian/Christmas", "SE Asia Standard Time" },
+ { "Indian/Cocos", "Myanmar Standard Time" },
+ { "Indian/Comoro", "E. Africa Standard Time" },
+ { "Indian/Kerguelen", "GMT Standard Time" },
+ { "Indian/Mahe", "Iran Standard Time" },
+ { "Indian/Maldives", "West Asia Standard Time" },
+ { "Indian/Mauritius", "Arabian Standard Time" },
+ { "Indian/Mayotte", "E. Africa Standard Time" },
+ { "Indian/Reunion", "Iran Standard Time" },
+ { "Pacific/Apia", "Dateline Standard Time" },
+ { "Pacific/Auckland", "New Zealand Standard Time" },
+ { "Pacific/Chatham", "Tonga Standard Time" },
+ { "Pacific/Chuuk", "West Pacific Standard Time" },
+ { "Pacific/Easter", "SA Pacific Standard Time" },
+ { "Pacific/Efate", "Central Pacific Standard Time" },
+ { "Pacific/Enderbury", "Tonga Standard Time" },
+ { "Pacific/Fakaofo", "Hawaiian Standard Time" },
+ { "Pacific/Fiji", "Fiji Standard Time" },
+ { "Pacific/Funafuti", "Fiji Standard Time" },
+ { "Pacific/Galapagos", "Mexico Standard Time" },
+ { "Pacific/Gambier", "Alaskan Standard Time" },
+ { "Pacific/Guadalcanal", "Central Pacific Standard Time" },
+ { "Pacific/Guam", "West Pacific Standard Time" },
+ { "Pacific/Honolulu", "Hawaiian Standard Time" },
+ { "Pacific/Johnston", "Hawaiian Standard Time" },
+ { "Pacific/Kiritimati", "Tonga Standard Time" },
+ { "Pacific/Kosrae", "Central Pacific Standard Time" },
+ { "Pacific/Kwajalein", "Fiji Standard Time" },
+ { "Pacific/Majuro", "Central Pacific Standard Time" },
+ { "Pacific/Marquesas", "Alaskan Standard Time" },
+ { "Pacific/Midway", "Samoa Standard Time" },
+ { "Pacific/Nauru", "Fiji Standard Time" },
+ { "Pacific/Niue", "Samoa Standard Time" },
+ { "Pacific/Norfolk", "Central Pacific Standard Time" },
+ { "Pacific/Noumea", "Central Pacific Standard Time" },
+ { "Pacific/Pago_Pago", "Samoa Standard Time" },
+ { "Pacific/Palau", "Yakutsk Standard Time" },
+ { "Pacific/Pitcairn", "Pacific Standard Time" },
+ { "Pacific/Pohnpei", "Central Pacific Standard Time" },
+ { "Pacific/Ponape", "Central Pacific Standard Time" },
+ { "Pacific/Port_Moresby", "West Pacific Standard Time" },
+ { "Pacific/Rarotonga", "Hawaiian Standard Time" },
+ { "Pacific/Saipan", "West Pacific Standard Time" },
+ { "Pacific/Tahiti", "Hawaiian Standard Time" },
+ { "Pacific/Tarawa", "Fiji Standard Time" },
+ { "Pacific/Tongatapu", "Tonga Standard Time" },
+ { "Pacific/Truk", "West Pacific Standard Time" },
+ { "Pacific/Wake", "Fiji Standard Time" },
+ { "Pacific/Wallis", "Fiji Standard Time" },
+};
+
+const gchar *
+e_cal_backend_ews_tz_util_get_msdn_equivalent (const gchar *ical_tz_location)
+{
+ const gchar *msdn_tz_location = NULL;
+
+ g_return_val_if_fail (ical_tz_location != NULL, NULL);
+
+ g_rec_mutex_lock (&tz_mutex);
+ msdn_tz_location = g_hash_table_lookup (ical_to_msdn, ical_tz_location);
+ g_rec_mutex_unlock (&tz_mutex);
+
+ return msdn_tz_location;
+}
+
+void
+e_cal_backend_ews_populate_tz_ical_to_msdn (void)
+{
+ gint i;
+
+ g_rec_mutex_lock (&tz_mutex);
+ if (ical_to_msdn != NULL) {
+ ical_to_msdn = g_hash_table_ref (ical_to_msdn);
+ g_rec_mutex_unlock (&tz_mutex);
+ return;
+ }
+
+ ical_to_msdn = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; i < G_N_ELEMENTS (ical_to_msdn_table); i++)
+ g_hash_table_insert (
+ ical_to_msdn,
+ (gchar *) ical_to_msdn_table[i].from,
+ (gchar *) ical_to_msdn_table[i].to);
+
+ g_rec_mutex_unlock (&tz_mutex);
+}
+
+const gchar *
+e_cal_backend_ews_tz_util_get_ical_equivalent (const gchar *msdn_tz_location)
+{
+ const gchar *ical_tz_location = NULL;
+
+ g_return_val_if_fail (msdn_tz_location != NULL, NULL);
+
+ g_rec_mutex_lock (&tz_mutex);
+ ical_tz_location = g_hash_table_lookup (msdn_to_ical, msdn_tz_location);
+ g_rec_mutex_unlock (&tz_mutex);
+
+ return ical_tz_location;
+}
+
+void
+e_cal_backend_ews_populate_tz_msdn_to_ical (void)
+{
+ gint i;
+
+ g_rec_mutex_lock (&tz_mutex);
+ if (msdn_to_ical != NULL) {
+ msdn_to_ical = g_hash_table_ref (msdn_to_ical);
+ g_rec_mutex_unlock (&tz_mutex);
+ return;
+ }
+
+ msdn_to_ical = g_hash_table_new (g_str_hash, g_str_equal);
+
+ for (i = 0; i < G_N_ELEMENTS (msdn_to_ical_table); i++)
+ g_hash_table_insert (
+ msdn_to_ical,
+ (gchar *) msdn_to_ical_table[i].from,
+ (gchar *) msdn_to_ical_table[i].to);
+
+ g_rec_mutex_unlock (&tz_mutex);
+}
+
+void
+e_cal_backend_ews_unref_tz_ical_to_msdn (void)
+{
+ g_rec_mutex_lock (&tz_mutex);
+ if (ical_to_msdn != NULL)
+ g_hash_table_unref (ical_to_msdn);
+ g_rec_mutex_unlock (&tz_mutex);
+}
+
+void
+e_cal_backend_ews_unref_tz_msdn_to_ical (void)
+{
+ g_rec_mutex_lock (&tz_mutex);
+ if (msdn_to_ical != NULL)
+ g_hash_table_unref (msdn_to_ical);
+ g_rec_mutex_unlock (&tz_mutex);
+}
+
+EwsCalendarConvertData *
+ews_calendar_convert_data_new (void)
+{
+ return g_new0 (EwsCalendarConvertData, 1);
+}
+
+void
+ews_calendar_convert_data_free (EwsCalendarConvertData *convert_data)
+{
+ if (convert_data != NULL) {
+ if (convert_data->connection != NULL)
+ g_clear_object (&convert_data->connection);
+ if (convert_data->comp != NULL)
+ g_clear_object (&convert_data->comp);
+ if (convert_data->old_comp != NULL)
+ g_clear_object (&convert_data->old_comp);
+ if (convert_data->default_zone != NULL)
+ icaltimezone_free (convert_data->default_zone, TRUE);
+ if (convert_data->icalcomp != NULL)
+ icalcomponent_free (convert_data->icalcomp);
+
+ g_free (convert_data->item_id);
+ g_free (convert_data->change_key);
+ g_free (convert_data->user_email);
+ g_free (convert_data->response_type);
+ g_slist_free_full (convert_data->users, g_free);
+
+ g_free (convert_data);
+ }
+}
+
+/*
* Iterate over the icalcomponent properties and collect attendees
*/
void
@@ -317,10 +975,151 @@ ewscal_add_timechange (ESoapMessage *msg,
}
}
+static void
+ewscal_set_absolute_date_transitions (ESoapMessage *msg,
+ GSList *absolute_date_transitions)
+{
+ GSList *l;
+
+ if (absolute_date_transitions == NULL)
+ return;
+
+ for (l = absolute_date_transitions; l != NULL; l = l->next) {
+ EEwsCalendarAbsoluteDateTransition *adt = l->data;
+
+ e_soap_message_start_element (msg, "AbsoluteDateTransition", NULL, NULL);
+
+ e_ews_message_write_string_parameter_with_attribute (
+ msg,
+ "To", NULL, adt->to->value,
+ "Kind", adt->to->kind);
+ e_ews_message_write_string_parameter (msg, "DateTime", NULL, adt->date_time);
+
+ e_soap_message_end_element (msg); /* "AbsoluteDateTransition" */
+ }
+}
+
+static void
+ewscal_set_recurring_day_transitions (ESoapMessage *msg,
+ GSList *recurring_day_transitions)
+{
+ GSList *l;
+
+ if (recurring_day_transitions == NULL)
+ return;
+
+ for (l = recurring_day_transitions; l != NULL; l = l->next) {
+ EEwsCalendarRecurringDayTransition *rdt = l->data;
+
+ e_soap_message_start_element (msg, "RecurringDayTransition", NULL, NULL);
+
+ e_ews_message_write_string_parameter_with_attribute (
+ msg,
+ "To", NULL, rdt->to->value,
+ "Kind", rdt->to->kind);
+ e_ews_message_write_string_parameter (msg, "TimeOffset", NULL, rdt->time_offset);
+ e_ews_message_write_string_parameter (msg, "Month", NULL, rdt->month);
+ e_ews_message_write_string_parameter (msg, "DayOfWeek", NULL, rdt->day_of_week);
+ e_ews_message_write_string_parameter (msg, "Occurrence", NULL, rdt->occurrence);
+
+ e_soap_message_end_element (msg); /* "RecurringDayTransition" */
+ }
+}
+
+static void
+ewscal_set_recurring_date_transitions (ESoapMessage *msg,
+ GSList *recurring_date_transitions)
+{
+ GSList *l;
+
+ if (recurring_date_transitions == NULL)
+ return;
+
+ for (l = recurring_date_transitions; l != NULL; l = l->next) {
+ EEwsCalendarRecurringDateTransition *rdt = l->data;
+
+ e_soap_message_start_element (msg, "RecurringDateTransition", NULL, NULL);
+
+ e_ews_message_write_string_parameter_with_attribute (
+ msg,
+ "To", NULL, rdt->to->value,
+ "Kind", rdt->to->kind);
+ e_ews_message_write_string_parameter (msg, "TimeOffset", NULL, rdt->time_offset);
+ e_ews_message_write_string_parameter (msg, "Month", NULL, rdt->month);
+ e_ews_message_write_string_parameter (msg, "Day", NULL, rdt->day);
+
+ e_soap_message_end_element (msg); /* "RecurringDateTransition" */
+ }
+}
+
void
ewscal_set_timezone (ESoapMessage *msg,
- const gchar *name,
- icaltimezone *icaltz)
+ const gchar *name,
+ EEwsCalendarTimeZoneDefinition *tzd)
+{
+ GSList *l;
+
+ if (name == NULL || tzd == NULL)
+ return;
+
+ e_soap_message_start_element (msg, name, NULL, NULL);
+ e_soap_message_add_attribute (msg, "Id", tzd->id, NULL, NULL);
+ e_soap_message_add_attribute (msg, "Name", tzd->name, NULL, NULL);
+
+ e_soap_message_start_element (msg, "Periods", NULL, NULL);
+ for (l = tzd->periods; l != NULL; l = l->next) {
+ EEwsCalendarPeriod *period = l->data;
+
+ e_soap_message_start_element (msg, "Period", NULL, NULL);
+ e_soap_message_add_attribute (msg, "Bias", period->bias, NULL, NULL);
+ e_soap_message_add_attribute (msg, "Name", period->name, NULL, NULL);
+ e_soap_message_add_attribute (msg, "Id", period->id, NULL, NULL);
+ e_soap_message_end_element (msg); /* "Period" */
+ }
+ e_soap_message_end_element (msg); /* "Periods" */
+
+ e_soap_message_start_element (msg, "TransitionsGroups", NULL, NULL);
+ for (l = tzd->transitions_groups; l != NULL; l = l->next) {
+ EEwsCalendarTransitionsGroup *tg = l->data;
+
+ e_soap_message_start_element (msg, "TransitionsGroup", NULL, NULL);
+ e_soap_message_add_attribute (msg, "Id", tg->id, NULL, NULL);
+
+ if (tg->transition != NULL) {
+ e_soap_message_start_element (msg, "Transition", NULL, NULL);
+ e_ews_message_write_string_parameter_with_attribute (
+ msg,
+ "To", NULL, tg->transition->value,
+ "Kind", tg->transition->kind);
+ e_soap_message_end_element (msg); /* "Transition" */
+ }
+
+ ewscal_set_absolute_date_transitions (msg, tg->absolute_date_transitions);
+ ewscal_set_recurring_day_transitions (msg, tg->recurring_day_transitions);
+ ewscal_set_recurring_date_transitions (msg, tg->recurring_date_transitions);
+
+ e_soap_message_end_element (msg); /* "TransitionsGroup" */
+ }
+ e_soap_message_end_element (msg); /* "TransitionsGroups" */
+
+ e_soap_message_start_element (msg, "Transitions", NULL, NULL);
+ e_soap_message_start_element (msg, "Transition", NULL, NULL);
+ e_ews_message_write_string_parameter_with_attribute (
+ msg,
+ "To", NULL, tzd->transitions->transition->value,
+ "Kind", tzd->transitions->transition->kind);
+ e_soap_message_end_element (msg); /* "Transition" */
+ ewscal_set_absolute_date_transitions (msg, tzd->transitions->absolute_date_transitions);
+ ewscal_set_recurring_day_transitions (msg, tzd->transitions->recurring_day_transitions);
+ ewscal_set_recurring_date_transitions (msg, tzd->transitions->recurring_date_transitions);
+ e_soap_message_end_element (msg); /* "Transitions" */
+
+ e_soap_message_end_element (msg); /* "StartTimeZone" */
+}
+
+void
+ewscal_set_meeting_timezone (ESoapMessage *msg,
+ icaltimezone *icaltz)
{
icalcomponent *comp;
icalproperty *prop;
@@ -360,7 +1159,7 @@ ewscal_set_timezone (ESoapMessage *msg,
if (!location)
location = icaltimezone_get_tznames (icaltz);
- e_soap_message_start_element (msg, name, NULL, NULL);
+ e_soap_message_start_element (msg, "MeetingTimeZone", NULL, NULL);
e_soap_message_add_attribute (msg, "TimeZoneName", location, NULL, NULL);
/* Fetch the timezone offsets for the standard (or only) zone.
@@ -818,3 +1617,950 @@ e_ews_clean_icalcomponent (icalcomponent *icalcomp)
if (changekey_prop != NULL)
icalcomponent_remove_property (icalcomp, changekey_prop);
}
+
+static void
+add_attendees_list_to_message (ESoapMessage *msg,
+ const gchar *listname,
+ GSList *list)
+{
+ GSList *item;
+
+ e_soap_message_start_element (msg, listname, NULL, NULL);
+
+ for (item = list; item != NULL; item = item->next) {
+ e_soap_message_start_element (msg, "Attendee", NULL, NULL);
+ e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
+
+ e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, item->data);
+
+ e_soap_message_end_element (msg); /* "Mailbox" */
+ e_soap_message_end_element (msg); /* "Attendee" */
+ }
+
+ e_soap_message_end_element (msg);
+}
+
+static void
+convert_sensitivity_calcomp_to_xml (ESoapMessage *msg,
+ icalcomponent *icalcomp)
+{
+ icalproperty *prop;
+
+ g_return_if_fail (msg != NULL);
+ g_return_if_fail (icalcomp != NULL);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+ if (prop) {
+ icalproperty_class classify = icalproperty_get_class (prop);
+ if (classify == ICAL_CLASS_PUBLIC) {
+ e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Normal");
+ } else if (classify == ICAL_CLASS_PRIVATE) {
+ e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Private");
+ } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+ e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Personal");
+ }
+ }
+}
+
+static void
+convert_categories_calcomp_to_xml (ESoapMessage *msg,
+ ECalComponent *comp,
+ icalcomponent *icalcomp)
+{
+ GSList *categ_list, *citer;
+
+ g_return_if_fail (msg != NULL);
+ g_return_if_fail (icalcomp != NULL);
+
+ if (comp) {
+ g_object_ref (comp);
+ } else {
+ icalcomponent *clone = icalcomponent_new_clone (icalcomp);
+
+ comp = e_cal_component_new ();
+ if (!e_cal_component_set_icalcomponent (comp, clone)) {
+ icalcomponent_free (clone);
+ g_object_unref (comp);
+
+ return;
+ }
+ }
+
+ e_cal_component_get_categories_list (comp, &categ_list);
+
+ g_object_unref (comp);
+
+ if (!categ_list)
+ return;
+
+ e_soap_message_start_element (msg, "Categories", NULL, NULL);
+
+ for (citer = categ_list; citer; citer = g_slist_next (citer)) {
+ const gchar *category = citer->data;
+
+ if (!category || !*category)
+ continue;
+
+ e_ews_message_write_string_parameter (msg, "String", NULL, category);
+ }
+
+ e_soap_message_end_element (msg); /* Categories */
+
+ e_cal_component_free_categories_list (categ_list);
+}
+
+static void
+convert_vevent_calcomp_to_xml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = convert_data->icalcomp;
+ ECalComponent *comp = e_cal_component_new ();
+ GSList *required = NULL, *optional = NULL, *resource = NULL;
+ icaltimetype dtstart, dtend;
+ icalproperty *prop;
+ gboolean has_alarms;
+ const gchar *value;
+
+ e_cal_component_set_icalcomponent (comp, icalcomp);
+
+ /* FORMAT OF A SAMPLE SOAP MESSAGE: http://msdn.microsoft.com/en-us/library/aa564690.aspx */
+
+ /* Prepare CalendarItem node in the SOAP message */
+ e_soap_message_start_element (msg, "CalendarItem", NULL, NULL);
+
+ /* subject */
+ value = icalcomponent_get_summary (icalcomp);
+ if (value)
+ e_ews_message_write_string_parameter (msg, "Subject", NULL, value);
+
+ convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+ /* description */
+ value = icalcomponent_get_description (icalcomp);
+ if (value)
+ e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, value, "BodyType",
"Text");
+
+ convert_categories_calcomp_to_xml (msg, comp, icalcomp);
+
+ /* set alarms */
+ has_alarms = e_cal_component_has_alarms (comp);
+ if (has_alarms)
+ ews_set_alarm (msg, comp);
+ else
+ e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+
+ /* start time, end time and meeting time zone */
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+ dtend = icalcomponent_get_dtend (icalcomp);
+
+ ewscal_set_time (msg, "Start", &dtstart, FALSE);
+ ewscal_set_time (msg, "End", &dtend, FALSE);
+ /* We have to do the time zone(s) later, or the server rejects the request */
+
+ /* All day event ? */
+ if (icaltime_is_date (dtstart))
+ e_ews_message_write_string_parameter (msg, "IsAllDayEvent", NULL, "true");
+
+ /*freebusy*/
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
+ if (!g_strcmp0 (icalproperty_get_value_as_string (prop), "TRANSPARENT"))
+ e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Free");
+ else
+ e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Busy");
+
+ /* location */
+ value = icalcomponent_get_location (icalcomp);
+ if (value)
+ e_ews_message_write_string_parameter (msg, "Location", NULL, value);
+
+ /* collect attendees */
+ e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
+
+ if (required != NULL) {
+ add_attendees_list_to_message (msg, "RequiredAttendees", required);
+ g_slist_free (required);
+ }
+ if (optional != NULL) {
+ add_attendees_list_to_message (msg, "OptionalAttendees", optional);
+ g_slist_free (optional);
+ }
+ if (resource != NULL) {
+ add_attendees_list_to_message (msg, "Resources", resource);
+ g_slist_free (resource);
+ }
+ /* end of attendees */
+
+ /* Recurrence */
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+ if (prop != NULL) {
+ ewscal_set_reccurence (msg, prop, &dtstart);
+ }
+
+ /* We have to cast these because libical puts a const pointer into the
+ * icaltimetype, but its basic read-only icaltimezone_foo() functions
+ * take a non-const pointer! */
+ if (e_ews_connection_satisfies_server_version (convert_data->connection, E_EWS_EXCHANGE_2010)) {
+ const gchar *ical_location;
+ const gchar *msdn_location;
+ icaltimezone *tzid;
+ GSList *msdn_locations = NULL;
+ GSList *tzds = NULL;
+
+ tzid = (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone);
+ ical_location = icaltimezone_get_location (tzid);
+ msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+
+ msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
+
+ tzid = (icaltimezone *)
+ (dtend.zone ? dtend.zone : convert_data->default_zone);
+ ical_location = icaltimezone_get_location (tzid);
+ msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+
+ msdn_locations = g_slist_prepend (msdn_locations, (gchar *) msdn_location);
+
+ msdn_locations = g_slist_reverse (msdn_locations);
+
+ if (e_ews_connection_get_server_time_zones_sync (
+ convert_data->connection,
+ EWS_PRIORITY_MEDIUM,
+ msdn_locations,
+ &tzds,
+ NULL,
+ NULL)) {
+ ewscal_set_timezone (msg, "StartTimeZone", tzds->data);
+ ewscal_set_timezone (msg, "EndTimeZone", tzds->data);
+ }
+
+ g_slist_free (msdn_locations);
+ g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
+ } else {
+ ewscal_set_meeting_timezone (
+ msg,
+ (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone));
+ }
+
+ e_soap_message_end_element (msg); /* "CalendarItem" */
+}
+
+static void
+convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = convert_data->icalcomp;
+ icalproperty *prop;
+ icaltimetype dt;
+ gint value;
+ gchar buffer[16];
+
+ e_soap_message_start_element (msg, "Task", NULL, NULL);
+
+ e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
+
+ convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+ e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, icalcomponent_get_description
(icalcomp), "BodyType", "Text");
+
+ convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
+ if (prop) {
+ dt = icalproperty_get_due (prop);
+ ewscal_set_time (msg, "DueDate", &dt, TRUE);
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop) {
+ value = icalproperty_get_percentcomplete (prop);
+ snprintf (buffer, 16, "%d", value);
+ e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ dt = icalproperty_get_dtstart (prop);
+ ewscal_set_time (msg, "StartDate", &dt, TRUE);
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop) {
+ switch (icalproperty_get_status (prop)) {
+ case ICAL_STATUS_INPROCESS:
+ e_ews_message_write_string_parameter (msg, "Status", NULL, "InProgress");
+ break;
+ case ICAL_STATUS_COMPLETED:
+ e_ews_message_write_string_parameter (msg, "Status", NULL, "Completed");
+ break;
+ default:
+ break;
+ }
+ }
+
+ e_soap_message_end_element (msg); /* "Task" */
+}
+
+static void
+convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = convert_data->icalcomp;
+ const gchar *text;
+
+ e_soap_message_start_element (msg, "Message", NULL, NULL);
+ e_ews_message_write_string_parameter (msg, "ItemClass", NULL, "IPM.StickyNote");
+
+ e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
+
+ convert_sensitivity_calcomp_to_xml (msg, icalcomp);
+
+ text = icalcomponent_get_description (icalcomp);
+ if (!text || !*text)
+ text = icalcomponent_get_summary (icalcomp);
+ e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, text, "BodyType", "Text");
+
+ convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
+
+ e_soap_message_end_element (msg); /* Message */
+}
+
+void
+e_cal_backend_ews_convert_calcomp_to_xml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+
+ switch (icalcomponent_isa (convert_data->icalcomp)) {
+ case ICAL_VEVENT_COMPONENT:
+ convert_vevent_calcomp_to_xml (msg, convert_data);
+ break;
+ case ICAL_VTODO_COMPONENT:
+ convert_vtodo_calcomp_to_xml (msg, convert_data);
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ convert_vjournal_calcomp_to_xml (msg, convert_data);
+ break;
+ default:
+ g_warn_if_reached ();
+ break;
+ }
+}
+
+static void
+convert_component_categories_to_updatexml (ECalComponent *comp,
+ ESoapMessage *msg,
+ const gchar *base_elem_name)
+{
+ GSList *categ_list = NULL, *citer;
+
+ g_return_if_fail (comp != NULL);
+ g_return_if_fail (msg != NULL);
+ g_return_if_fail (base_elem_name != NULL);
+
+ e_cal_component_get_categories_list (comp, &categ_list);
+ e_ews_message_start_set_item_field (msg, "Categories", "item", base_elem_name);
+ e_soap_message_start_element (msg, "Categories", NULL, NULL);
+
+ for (citer = categ_list; citer; citer = g_slist_next (citer)) {
+ const gchar *category = citer->data;
+
+ if (!category || !*category)
+ continue;
+
+ e_ews_message_write_string_parameter (msg, "String", NULL, category);
+ }
+
+ e_soap_message_end_element (msg); /* Categories */
+ e_ews_message_end_set_item_field (msg);
+
+ e_cal_component_free_categories_list (categ_list);
+}
+
+static void
+convert_vevent_property_to_updatexml (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *value,
+ const gchar *prefix,
+ const gchar *attr_name,
+ const gchar *attr_value)
+{
+ e_ews_message_start_set_item_field (msg, name, prefix, "CalendarItem");
+ e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+ e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vevent_component_to_updatexml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+ icalcomponent *icalcomp_old = e_cal_component_get_icalcomponent (convert_data->old_comp);
+ GSList *required = NULL, *optional = NULL, *resource = NULL;
+ icaltimetype dtstart, dtend, dtstart_old, dtend_old;
+ icalproperty *prop, *transp;
+ const gchar *org_email_address = NULL, *value = NULL, *old_value = NULL;
+ gboolean has_alarms, has_alarms_old, dt_changed = FALSE;
+ 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) {
+ /* A single occurrence ? */
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY);
+ if (prop != NULL) {
+ recid = icalproperty_get_value_as_string_r (prop);
+ e_ews_message_start_item_change (
+ msg,
+ E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM,
+ convert_data->item_id,
+ convert_data->change_key,
+ e_cal_backend_ews_rid_to_index (
+ convert_data->default_zone,
+ recid,
+ icalcomp_old,
+ &error));
+ g_free (recid);
+ } else {
+ e_ews_message_start_item_change (
+ msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+ convert_data->item_id, convert_data->change_key, 0);
+ }
+ } else e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+ convert_data->item_id, convert_data->change_key, 0);
+
+ /* subject */
+ value = icalcomponent_get_summary (icalcomp);
+ old_value = icalcomponent_get_summary (icalcomp_old);
+ if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+ (value && old_value == NULL)) {
+ convert_vevent_property_to_updatexml (msg, "Subject", value, "item", NULL, NULL);
+ } else if (!value && old_value)
+ convert_vevent_property_to_updatexml (msg, "Subject", "", "item", NULL, NULL);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+ if (prop) {
+ icalproperty_class classify = icalproperty_get_class (prop);
+ if (classify == ICAL_CLASS_PUBLIC) {
+ convert_vevent_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_PRIVATE) {
+ convert_vevent_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+ convert_vevent_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
+ }
+ }
+
+ /*description*/
+ value = icalcomponent_get_description (icalcomp);
+ old_value = icalcomponent_get_description (icalcomp_old);
+ if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+ (value && old_value == NULL)) {
+ convert_vevent_property_to_updatexml (msg, "Body", value, "item", "BodyType", "Text");
+ } else if (!value && old_value)
+ convert_vevent_property_to_updatexml (msg, "Body", "", "item", "BodyType", "Text");
+
+ /*update alarm items*/
+ has_alarms = e_cal_component_has_alarms (convert_data->comp);
+ if (has_alarms) {
+ alarm = ews_get_alarm (convert_data->comp);
+ has_alarms_old = e_cal_component_has_alarms (convert_data->old_comp);
+ if (has_alarms_old)
+ alarm_old = ews_get_alarm (convert_data->old_comp);
+ if (!(alarm == alarm_old)) {
+ gchar buf[20];
+ snprintf (buf, 20, "%d", alarm);
+ convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "true", "item", NULL,
NULL);
+ convert_vevent_property_to_updatexml (msg, "ReminderMinutesBeforeStart", buf, "item",
NULL, NULL);
+ }
+ }
+ else convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "false", "item", NULL, NULL);
+
+ /* Categories */
+ convert_component_categories_to_updatexml (convert_data->comp, msg, "CalendarItem");
+
+ /*location*/
+ value = icalcomponent_get_location (icalcomp);
+ old_value = icalcomponent_get_location (icalcomp_old);
+ if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
+ (value && old_value == NULL)) {
+ convert_vevent_property_to_updatexml (msg, "Location", value, "calendar", NULL, NULL);
+ } else if (!value && old_value)
+ convert_vevent_property_to_updatexml (msg, "Location", "", "calendar", NULL, NULL);
+
+ /*freebusy*/
+ transp = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
+ value = icalproperty_get_value_as_string (transp);
+ transp = icalcomponent_get_first_property (icalcomp_old, ICAL_TRANSP_PROPERTY);
+ old_value = icalproperty_get_value_as_string (transp);
+ if (g_strcmp0 (value, old_value)) {
+ if (!g_strcmp0 (value, "TRANSPARENT"))
+ convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Free" ,
"calendar", NULL, NULL);
+ else
+ convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Busy" ,
"calendar", NULL, NULL);
+ }
+
+ org_email_address = e_ews_collect_organizer (icalcomp);
+ if (org_email_address && g_ascii_strcasecmp (org_email_address, convert_data->user_email)) {
+ e_ews_message_end_item_change (msg);
+ return;
+ }
+ /* Update other properties allowed only for meeting organizers*/
+ /*meeting dates*/
+ dtstart = icalcomponent_get_dtstart (icalcomp);
+ dtend = icalcomponent_get_dtend (icalcomp);
+ dtstart_old = icalcomponent_get_dtstart (icalcomp_old);
+ dtend_old = icalcomponent_get_dtend (icalcomp_old);
+ if (icaltime_compare (dtstart, dtstart_old) != 0) {
+ e_ews_message_start_set_item_field (msg, "Start", "calendar","CalendarItem");
+ ewscal_set_time (msg, "Start", &dtstart, FALSE);
+ e_ews_message_end_set_item_field (msg);
+ dt_changed = TRUE;
+ }
+
+ if (icaltime_compare (dtend, dtend_old) != 0) {
+ e_ews_message_start_set_item_field (msg, "End", "calendar", "CalendarItem");
+ ewscal_set_time (msg, "End", &dtend, FALSE);
+ e_ews_message_end_set_item_field (msg);
+ dt_changed = TRUE;
+ }
+
+ /*Check for All Day Event*/
+ if (dt_changed) {
+ if (icaltime_is_date (dtstart))
+ convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "true", "calendar", NULL,
NULL);
+ else
+ convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "false", "calendar",
NULL, NULL);
+ }
+
+ /*need to test it*/
+ e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
+ if (required != NULL) {
+ e_ews_message_start_set_item_field (msg, "RequiredAttendees", "calendar", "CalendarItem");
+
+ add_attendees_list_to_message (msg, "RequiredAttendees", required);
+ g_slist_free (required);
+
+ e_ews_message_end_set_item_field (msg);
+ }
+ if (optional != NULL) {
+ e_ews_message_start_set_item_field (msg, "OptionalAttendees", "calendar", "CalendarItem");
+
+ add_attendees_list_to_message (msg, "OptionalAttendees", optional);
+ g_slist_free (optional);
+
+ e_ews_message_end_set_item_field (msg);
+ }
+ if (resource != NULL) {
+ e_ews_message_start_set_item_field (msg, "Resources", "calendar", "CalendarItem");
+
+ add_attendees_list_to_message (msg, "Resources", resource);
+ g_slist_free (resource);
+
+ e_ews_message_end_set_item_field (msg);
+ }
+
+ /* Recurrence */
+ value = NULL; old_value = NULL;
+ prop = icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY);
+ if (prop != NULL)
+ old_value = icalproperty_get_value_as_string (prop);
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
+ if (prop != NULL)
+ value = icalproperty_get_value_as_string (prop);
+
+ if (prop != NULL && g_strcmp0 (value, old_value)) {
+ e_ews_message_start_set_item_field (msg, "Recurrence", "calendar", "CalendarItem");
+ ewscal_set_reccurence (msg, prop, &dtstart);
+ e_ews_message_end_set_item_field (msg);
+ }
+
+ /* We have to cast these because libical puts a const pointer into the
+ * icaltimetype, but its basic read-only icaltimezone_foo() functions
+ * take a non-const pointer! */
+ if (e_ews_connection_satisfies_server_version (convert_data->connection, E_EWS_EXCHANGE_2010)) {
+ const gchar *ical_location;
+ const gchar *msdn_location;
+ icaltimezone *tzid;
+ GSList *msdn_locations = NULL;
+ GSList *tzds = NULL;
+
+ if (dtstart.zone != NULL) {
+ tzid = (icaltimezone *) dtstart.zone;
+ ical_location = icaltimezone_get_location (tzid);
+ msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+ msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
+ }
+
+ if (dtend.zone != NULL) {
+ tzid = (icaltimezone *) dtend.zone;
+ ical_location = icaltimezone_get_location (tzid);
+ msdn_location = e_cal_backend_ews_tz_util_get_msdn_equivalent (ical_location);
+ msdn_locations = g_slist_append (msdn_locations, (gchar *) msdn_location);
+ }
+
+ if (e_ews_connection_get_server_time_zones_sync (
+ convert_data->connection,
+ EWS_PRIORITY_MEDIUM,
+ msdn_locations,
+ &tzds,
+ NULL,
+ NULL)) {
+ GSList *tmp;
+
+ tmp = tzds;
+ if (dtstart.zone != NULL) {
+ e_ews_message_start_set_item_field (msg, "StartTimeZone", "calendar",
"CalendarItem");
+ ewscal_set_timezone (msg, "StartTimeZone", tmp->data);
+ e_ews_message_end_set_item_field (msg);
+
+ /*
+ * Exchange server is smart enough to return the list of
+ * ServerTimeZone without repeated elements
+ */
+ if (tmp->next != NULL)
+ tmp = tmp->next;
+ }
+
+ if (dtend.zone != NULL) {
+ e_ews_message_start_set_item_field (msg, "EndTimeZone", "calendar",
"CalendarItem");
+ ewscal_set_timezone (msg, "EndTimeZone", tmp->data);
+ e_ews_message_end_set_item_field (msg);
+ }
+ }
+
+ g_slist_free (msdn_locations);
+ g_slist_free_full (tzds, (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
+ } else {
+ e_ews_message_start_set_item_field (msg, "MeetingTimeZone", "calendar", "CalendarItem");
+ ewscal_set_meeting_timezone (
+ msg,
+ (icaltimezone *) (dtstart.zone ? dtstart.zone : convert_data->default_zone));
+ e_ews_message_end_set_item_field (msg);
+ }
+
+ e_ews_message_end_item_change (msg);
+}
+
+static void
+convert_vtodo_property_to_updatexml (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *value,
+ const gchar *prefix,
+ const gchar *attr_name,
+ const gchar *attr_value)
+{
+ e_ews_message_start_set_item_field (msg, name, prefix, "Task");
+ e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+ e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vtodo_component_to_updatexml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+ icalproperty *prop;
+ icaltimetype dt;
+ gint value;
+ gchar buffer[16];
+
+ e_ews_message_start_item_change (
+ msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+ convert_data->item_id, convert_data->change_key, 0);
+
+ convert_vtodo_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item",
NULL, NULL);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+ if (prop) {
+ icalproperty_class classify = icalproperty_get_class (prop);
+ if (classify == ICAL_CLASS_PUBLIC) {
+ convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_PRIVATE) {
+ convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+ convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
+ }
+ }
+
+ convert_vtodo_property_to_updatexml (msg, "Body", icalcomponent_get_description (icalcomp), "item",
"BodyType", "Text");
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
+ if (prop) {
+ dt = icalproperty_get_due (prop);
+ e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
+ ewscal_set_time (msg, "DueDate", &dt, TRUE);
+ e_ews_message_end_set_item_field (msg);
+ } else {
+ e_ews_message_add_delete_item_field (msg, "DueDate", "task");
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
+ if (prop) {
+ value = icalproperty_get_percentcomplete (prop);
+ snprintf (buffer, 16, "%d", value);
+ e_ews_message_start_set_item_field (msg, "PercentComplete", "task", "Task");
+ e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
+ e_ews_message_end_set_item_field (msg);
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
+ if (prop) {
+ dt = icalproperty_get_dtstart (prop);
+ e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
+ ewscal_set_time (msg, "StartDate", &dt, TRUE);
+ e_ews_message_end_set_item_field (msg);
+ } else {
+ e_ews_message_add_delete_item_field (msg, "StartDate", "task");
+ }
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
+ if (prop) {
+ switch (icalproperty_get_status (prop)) {
+ case ICAL_STATUS_INPROCESS:
+ convert_vtodo_property_to_updatexml (msg, "Status", "InProgress", "task", NULL, NULL);
+ break;
+ case ICAL_STATUS_COMPLETED:
+ convert_vtodo_property_to_updatexml (msg, "Status", "Completed", "task", NULL, NULL);
+ break;
+ case ICAL_STATUS_NONE:
+ case ICAL_STATUS_NEEDSACTION:
+ convert_vtodo_property_to_updatexml (msg, "Status", "NotStarted", "task", NULL, NULL);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Categories */
+ convert_component_categories_to_updatexml (convert_data->comp, msg, "Task");
+
+ e_ews_message_end_item_change (msg);
+}
+
+static void
+convert_vjournal_property_to_updatexml (ESoapMessage *msg,
+ const gchar *name,
+ const gchar *value,
+ const gchar *prefix,
+ const gchar *attr_name,
+ const gchar *attr_value)
+{
+ e_ews_message_start_set_item_field (msg, name, prefix, "Message");
+ e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
+ e_ews_message_end_set_item_field (msg);
+}
+
+static void
+convert_vjournal_component_to_updatexml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+ icalproperty *prop;
+ const gchar *text;
+
+ e_ews_message_start_item_change (
+ msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
+ convert_data->item_id, convert_data->change_key, 0);
+
+ convert_vjournal_property_to_updatexml (msg, "ItemClass", "IPM.StickyNote", "item", NULL, NULL);
+ convert_vjournal_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item",
NULL, NULL);
+
+ prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
+ if (prop) {
+ icalproperty_class classify = icalproperty_get_class (prop);
+ if (classify == ICAL_CLASS_PUBLIC) {
+ convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_PRIVATE) {
+ convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
+ } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
+ convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
+ }
+ }
+
+ text = icalcomponent_get_description (icalcomp);
+ if (!text || !*text)
+ text = icalcomponent_get_summary (icalcomp);
+
+ convert_vjournal_property_to_updatexml (msg, "Body", text, "item", "BodyType", "Text");
+
+ /* Categories */
+ convert_component_categories_to_updatexml (convert_data->comp, msg, "Message");
+
+ e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_convert_component_to_updatexml (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent (convert_data->comp);
+
+ switch (icalcomponent_isa (icalcomp)) {
+ case ICAL_VEVENT_COMPONENT:
+ convert_vevent_component_to_updatexml (msg, user_data);
+ break;
+ case ICAL_VTODO_COMPONENT:
+ convert_vtodo_component_to_updatexml (msg, user_data);
+ break;
+ case ICAL_VJOURNAL_COMPONENT:
+ convert_vjournal_component_to_updatexml (msg, user_data);
+ break;
+ default:
+ break;
+ }
+}
+
+guint
+e_cal_backend_ews_rid_to_index (icaltimezone *timezone,
+ const gchar *rid,
+ icalcomponent *comp,
+ GError **error)
+{
+ guint index = 1;
+ icalproperty *prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
+ struct icalrecurrencetype rule = icalproperty_get_rrule (prop);
+ struct icaltimetype dtstart = icalcomponent_get_dtstart (comp);
+ icalrecur_iterator * ritr;
+ icaltimetype next, o_time;
+
+ /* icalcomponent_get_datetime needs a fix to initialize ret.zone to NULL. If a timezone is not
+ * found in libical, it remains uninitialized in that function causing invalid read or crash. so
+ * we set the timezone as we cannot identify if it has a valid timezone or not */
+ dtstart.zone = timezone;
+ ritr = icalrecur_iterator_new (rule, dtstart);
+ next = icalrecur_iterator_next (ritr);
+ o_time = icaltime_from_string (rid);
+ o_time.zone = dtstart.zone;
+
+ for (; !icaltime_is_null_time (next); next = icalrecur_iterator_next (ritr), index++) {
+ if (icaltime_compare_date_only (o_time, next) == 0)
+ break;
+ }
+
+ icalrecur_iterator_free (ritr);
+
+ if (icaltime_is_null_time (next)) {
+ g_propagate_error (
+ error, EDC_ERROR_EX (OtherError,
+ "Invalid occurrence ID"));
+ }
+
+ return index;
+}
+
+void
+e_cal_backend_ews_clear_reminder_is_set (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+
+ e_ews_message_start_item_change (
+ msg,
+ convert_data->change_type,
+ convert_data->item_id,
+ convert_data->change_key,
+ convert_data->index);
+
+ e_ews_message_start_set_item_field (msg, "ReminderIsSet","item", "CalendarItem");
+
+ e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+
+ e_ews_message_end_set_item_field (msg);
+
+ e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_prepare_free_busy_request (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *convert_data = user_data;
+ GSList *addr;
+ icaltimetype t_start, t_end;
+ icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
+
+ ewscal_set_availability_timezone (msg, utc_zone);
+
+ e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
+
+ for (addr = convert_data->users; addr; addr = addr->next) {
+ e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
+
+ e_soap_message_start_element (msg, "Email", NULL, NULL);
+ e_ews_message_write_string_parameter (msg, "Address", NULL, addr->data);
+ e_soap_message_end_element (msg); /* "Email" */
+
+ e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
+ e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
+
+ e_soap_message_end_element (msg); /* "MailboxData" */
+ }
+
+ e_soap_message_end_element (msg); /* "MailboxDataArray" */
+
+ e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
+
+ e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
+ t_start = icaltime_from_timet_with_zone (convert_data->start, 0, utc_zone);
+ t_end = icaltime_from_timet_with_zone (convert_data->end, 0, utc_zone);
+ ewscal_set_time (msg, "StartTime", &t_start, FALSE);
+ ewscal_set_time (msg, "EndTime", &t_end, FALSE);
+ e_soap_message_end_element (msg); /* "TimeWindow" */
+
+ e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
+ e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
+
+ e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
+}
+
+void
+e_cal_backend_ews_prepare_set_free_busy_status (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *data = user_data;
+
+ e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM, data->item_id, data->change_key, 0);
+
+ e_ews_message_start_set_item_field (msg, "LegacyFreeBusyStatus", "calendar", "CalendarItem");
+
+ e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus", NULL, "Free");
+
+ e_ews_message_end_set_item_field (msg);
+
+ e_ews_message_end_item_change (msg);
+}
+
+void
+e_cal_backend_ews_prepare_accept_item_request (ESoapMessage *msg,
+ gpointer user_data)
+{
+ EwsCalendarConvertData *data = user_data;
+ const gchar *response_type = data->response_type;
+
+ /* FORMAT OF A SAMPLE SOAP MESSAGE:
http://msdn.microsoft.com/en-us/library/aa566464%28v=exchg.140%29.aspx
+ * Accept and Decline meeting have same method code (10032)
+ * The real status is reflected at Attendee property PARTSTAT
+ * need to find current user as attendee and make a decision what to do.
+ * Prepare AcceptItem node in the SOAP message */
+
+ if (response_type && !g_ascii_strcasecmp (response_type, "ACCEPTED"))
+ e_soap_message_start_element (msg, "AcceptItem", NULL, NULL);
+ else if (response_type && !g_ascii_strcasecmp (response_type, "DECLINED"))
+ e_soap_message_start_element (msg, "DeclineItem", NULL, NULL);
+ else
+ e_soap_message_start_element (msg, "TentativelyAcceptItem", NULL, NULL);
+
+ e_soap_message_start_element (msg, "ReferenceItemId", NULL, NULL);
+ e_soap_message_add_attribute (msg, "Id", data->item_id, NULL, NULL);
+ e_soap_message_add_attribute (msg, "ChangeKey", data->change_key, NULL, NULL);
+ e_soap_message_end_element (msg); /* "ReferenceItemId" */
+
+ /* end of "AcceptItem" */
+ e_soap_message_end_element (msg);
+}
diff --git a/src/calendar/e-cal-backend-ews-utils.h b/src/calendar/e-cal-backend-ews-utils.h
index 6f265c0..d7b654d 100644
--- a/src/calendar/e-cal-backend-ews-utils.h
+++ b/src/calendar/e-cal-backend-ews-utils.h
@@ -26,18 +26,43 @@
#include <libical/icaltimezone.h>
#include "server/e-ews-connection.h"
+#include "server/e-ews-item-change.h"
#include "e-cal-backend-ews.h"
G_BEGIN_DECLS
+#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
+#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
+
#define MINUTES_IN_HOUR 60
#define SECS_IN_MINUTE 60
+typedef struct {
+ EEwsConnection *connection;
+ icaltimezone *default_zone;
+ gchar *user_email;
+ gchar *response_type; /* Accept */
+ GSList *users;
+ ECalComponent *comp;
+ ECalComponent *old_comp;
+ icalcomponent *icalcomp;
+ gchar *item_id;
+ gchar *change_key;
+ EEwsItemChangeType change_type;
+ gint index;
+ time_t start;
+ time_t end;
+} EwsCalendarConvertData;
+
+EwsCalendarConvertData *ews_calendar_convert_data_new (void);
+void ews_calendar_convert_data_free (EwsCalendarConvertData *convert_data);
+
const gchar *e_ews_collect_organizer (icalcomponent *comp);
void e_ews_collect_attendees (icalcomponent *comp, GSList **required, GSList **optional, GSList **resource);
void ewscal_set_time (ESoapMessage *msg, const gchar *name, icaltimetype *t, gboolean with_timezone);
-void ewscal_set_timezone (ESoapMessage *msg, const gchar *name, icaltimezone *icaltz);
+void ewscal_set_timezone (ESoapMessage *msg, const gchar *name, EEwsCalendarTimeZoneDefinition *tzd);
+void ewscal_set_meeting_timezone (ESoapMessage *msg, icaltimezone *icaltz);
void ewscal_set_availability_timezone (ESoapMessage *msg, icaltimezone *icaltz);
void ewscal_set_reccurence (ESoapMessage *msg, icalproperty *rrule, icaltimetype *dtstart);
void ewscal_set_reccurence_exceptions (ESoapMessage *msg, icalcomponent *comp);
@@ -47,6 +72,22 @@ void ews_set_alarm (ESoapMessage *msg, ECalComponent *comp);
gint ews_get_alarm (ECalComponent *comp);
void e_ews_clean_icalcomponent (icalcomponent *icalcomp);
+const gchar *e_cal_backend_ews_tz_util_get_msdn_equivalent (const gchar *ical_tz_location);
+const gchar *e_cal_backend_ews_tz_util_get_ical_equivalent (const gchar *msdn_tz_location);
+void e_cal_backend_ews_populate_tz_ical_to_msdn (void);
+void e_cal_backend_ews_populate_tz_msdn_to_ical (void);
+void e_cal_backend_ews_unref_tz_ical_to_msdn (void);
+void e_cal_backend_ews_unref_tz_msdn_to_ical (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_free_busy_request (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);
+
+guint e_cal_backend_ews_rid_to_index (icaltimezone *timezone, const gchar *rid, icalcomponent *comp, GError
**error);
+
G_END_DECLS
#endif
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 32aab8d..e58bc6b 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -40,9 +40,6 @@
#include <libical/icalproperty.h>
#include <libical/icalparameter.h>
-#include "server/e-ews-item-change.h"
-#include "server/e-ews-message.h"
-#include "server/e-soap-response.h"
#include "server/e-source-ews-folder.h"
#include "utils/ews-camel-common.h"
@@ -91,13 +88,30 @@ struct _ECalBackendEwsPrivate {
#define PRIV_LOCK(p) (g_rec_mutex_lock (&(p)->rec_mutex))
#define PRIV_UNLOCK(p) (g_rec_mutex_unlock (&(p)->rec_mutex))
-#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
-#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
-
#define SYNC_KEY "sync-state"
#define EWS_MAX_FETCH_COUNT 100
#define REFRESH_INTERVAL 600
+#define GET_ITEMS_SYNC_PROPERTIES \
+ "item:Attachments" \
+ " item:Categories" \
+ " item:HasAttachments" \
+ " item:MimeContent" \
+ " calendar:UID" \
+ " calendar:Resources" \
+ " calendar:ModifiedOccurrences" \
+ " calendar:RequiredAttendees" \
+ " calendar:OptionalAttendees"
+
+#define GET_ITEMS_SYNC_PROPERTIES_2007 \
+ GET_ITEMS_SYNC_PROPERTIES \
+ " calendar:TimeZone"
+
+#define GET_ITEMS_SYNC_PROPERTIES_2010 \
+ GET_ITEMS_SYNC_PROPERTIES \
+ " calendar:StartTimeZone"
+
+
#define e_data_cal_error_if_fail(expr, _code) \
G_STMT_START { \
if (G_LIKELY (expr)) { \
@@ -113,13 +127,10 @@ struct _ECalBackendEwsPrivate {
} \
} G_STMT_END
+/* Forward Declarations */
static void ews_cal_component_get_item_id (ECalComponent *comp, gchar **itemid, gchar **changekey);
static gboolean ews_start_sync (gpointer data);
-static icaltimezone * e_cal_get_timezone_from_ical_component (ECalBackend *backend, icalcomponent *comp);
static gpointer ews_start_sync_thread (gpointer data);
-
-
-/* Forward Declarations */
static void e_cal_backend_ews_authenticator_init
(ESourceAuthenticatorInterface *interface);
@@ -292,37 +303,44 @@ exit:
e_data_cal_respond_add_timezone (cal, context, error);
}
-typedef struct {
- ECalBackendEws *cbews;
- EDataCal *cal;
- guint32 context;
- gchar *itemid;
- gchar *changekey;
- gboolean is_occurrence;
- gint instance_index;
-} EwsDiscardAlarmData;
-
-static void clear_reminder_is_set (ESoapMessage *msg, gpointer user_data)
-{
- EwsDiscardAlarmData *edad = user_data;
- EEwsItemChangeType change_type;
-
- if (edad->is_occurrence)
- change_type = E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM;
- else
- change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
-
- e_ews_message_start_item_change (
- msg, change_type,
- edad->itemid, edad->changekey, edad->instance_index);
+typedef enum {
+ E_EWS_ATTACHMENT_TYPE_NOTHING = 0,
+ E_EWS_ATTACHMENT_TYPE_CREATE,
+ E_EWS_ATTACHMENT_TYPE_UPDATE
+} EEwsAttachmentType;
- e_ews_message_start_set_item_field (msg, "ReminderIsSet","item", "CalendarItem");
+typedef struct {
+ ECalBackendEws *cbews; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+ ECalComponent *comp; /* Create, Remove, Modify, FreeBusy, Attachments */
+ ECalComponent *extra_comp; /* Modify, Attachments: used as old_comp. Remove: used as parent_comp */
+ EDataCal *cal; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+ GSList *users; /* FreeBusy */
+ gchar *item_id; /* Accept, Remove, Modify, Attachments, DiscardAlarm */
+ gchar *rid; /* Remove */
+ EEwsAttachmentType cb_type; /* Attachments */
+ ECalObjModType mod; /* Remove */
+ guint32 context; /* Create, Remove, Modify, FreeBusy, Attachments, DiscardAlarm */
+} EwsCalendarAsyncData;
- e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
+static void
+e_cal_backend_ews_async_data_free (EwsCalendarAsyncData *async_data)
+{
+ if (async_data != NULL) {
+ if (async_data->cbews != NULL)
+ g_clear_object (&async_data->cbews);
+ if (async_data->comp != NULL)
+ g_clear_object (&async_data->comp);
+ if (async_data->extra_comp != NULL)
+ g_clear_object (&async_data->extra_comp);
+ if (async_data->cal != NULL)
+ g_clear_object (&async_data->cal);
- e_ews_message_end_set_item_field (msg);
+ g_slist_free_full (async_data->users, g_free);
+ g_free (async_data->item_id);
+ g_free (async_data->rid);
- e_ews_message_end_item_change (msg);
+ g_free (async_data);
+ }
}
static void
@@ -331,7 +349,7 @@ ews_cal_discard_alarm_cb (GObject *object,
gpointer user_data)
{
EEwsConnection *cnc = E_EWS_CONNECTION (object);
- EwsDiscardAlarmData *edad = user_data;
+ EwsCalendarAsyncData *edad = user_data;
GError *error = NULL;
if (!e_ews_connection_update_items_finish (cnc, res, NULL, &error)) {
@@ -341,11 +359,7 @@ ews_cal_discard_alarm_cb (GObject *object,
convert_error_to_edc_error (&error);
e_data_cal_respond_discard_alarm (edad->cal, edad->context, error);
- g_free (edad->itemid);
- g_free (edad->changekey);
- g_object_unref (edad->cbews);
- g_object_unref (edad->cal);
- g_free (edad);
+ e_cal_backend_ews_async_data_free (edad);
}
static void
@@ -359,7 +373,8 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
{
ECalBackendEws *cbews = (ECalBackendEws *) backend;
ECalBackendEwsPrivate *priv;
- EwsDiscardAlarmData *edad;
+ EwsCalendarAsyncData *edad;
+ EwsCalendarConvertData convert_data;
ECalComponent *comp;
GError *local_error = NULL;
@@ -386,7 +401,7 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
/* FIXME: Can't there be multiple alarms for each event? Or does
* Exchange not support that? */
- edad = g_new0 (EwsDiscardAlarmData, 1);
+ edad = g_new0 (EwsCalendarAsyncData, 1);
edad->cbews = g_object_ref (cbews);
edad->cal = g_object_ref (cal);
edad->context = context;
@@ -394,31 +409,31 @@ e_cal_backend_ews_discard_alarm (ECalBackend *backend,
if (e_cal_component_has_recurrences (comp)) {
gint *index;
- edad->is_occurrence = TRUE;
+ convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM;
e_cal_component_get_sequence (comp, &index);
if (index != NULL) {
/*Microsoft is counting the occurrences starting from 1
where EcalComponent is starting from zerro */
- edad->instance_index = *index + 1;
+ convert_data.index = *index + 1;
e_cal_component_free_sequence (index);
} else {
- edad->is_occurrence = FALSE;
- edad->instance_index = -1;
+ convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
+ convert_data.index = -1;
}
- }
- else {
- edad->is_occurrence = FALSE;
- edad->instance_index = -1;
+ } else {
+ convert_data.change_type = E_EWS_ITEMCHANGE_TYPE_ITEM;
+ convert_data.index = -1;
}
- ews_cal_component_get_item_id (comp, &edad->itemid, &edad->changekey);
+ ews_cal_component_get_item_id (comp, &convert_data.item_id, &convert_data.change_key);
e_ews_connection_update_items (
priv->cnc, EWS_PRIORITY_MEDIUM,
"AlwaysOverwrite", NULL,
"SendToNone", NULL,
- clear_reminder_is_set, edad,
+ e_cal_backend_ews_clear_reminder_is_set,
+ &convert_data,
priv->cancellable,
ews_cal_discard_alarm_cb,
edad);
@@ -994,24 +1009,44 @@ ews_cal_append_exdate (ECalBackendEws *cbews,
g_object_unref (old_comp);
}
-typedef struct {
- ECalBackendEws *cbews;
- EDataCal *cal;
- ECalComponent *comp, *parent;
- guint32 context;
- EwsId item_id;
- guint index;
- gchar *rid;
- gboolean modified;
- ECalObjModType mod;
-} EwsRemoveData;
+static icaltimezone *
+e_cal_backend_ews_get_timezone_from_ical_component (ECalBackend *backend,
+ icalcomponent *comp)
+{
+ ETimezoneCache *timezone_cache;
+ icalproperty *prop = NULL;
+ const gchar *tzid = NULL;
+
+ timezone_cache = E_TIMEZONE_CACHE (backend);
+
+ prop = icalcomponent_get_first_property (comp, ICAL_DTSTART_PROPERTY);
+ if (prop != NULL) {
+ icalparameter *param = NULL;
+
+ param = icalproperty_get_first_parameter (prop, ICAL_TZID_PARAMETER);
+ if (param != NULL) {
+ tzid = icalparameter_get_tzid (param);
+ } else {
+ struct icaltimetype dtstart;
+
+ dtstart = icalproperty_get_dtstart (prop);
+ if (dtstart.is_utc)
+ tzid = "UTC";
+ }
+ }
+
+ if (tzid != NULL)
+ return e_timezone_cache_get_timezone (timezone_cache, tzid);
+
+ return NULL;
+}
static void
ews_cal_remove_object_cb (GObject *object,
GAsyncResult *res,
gpointer user_data)
{
- EwsRemoveData *remove_data = user_data;
+ EwsCalendarAsyncData *remove_data = user_data;
GSimpleAsyncResult *simple;
GError *error = NULL;
@@ -1020,8 +1055,11 @@ ews_cal_remove_object_cb (GObject *object,
if (!g_simple_async_result_propagate_error (simple, &error) || error->code ==
EWS_CONNECTION_ERROR_ITEMNOTFOUND) {
/* FIXME: This is horrid. Will bite us when we start to delete
* more than one item at a time... */
- if (remove_data->comp) ews_cal_delete_comp (remove_data->cbews, remove_data->comp,
remove_data->item_id.id);
- if (remove_data->parent) ews_cal_append_exdate (remove_data->cbews, remove_data->parent,
remove_data->rid, remove_data->mod);
+ if (remove_data->comp != NULL)
+ ews_cal_delete_comp (remove_data->cbews, remove_data->comp, remove_data->item_id);
+ if (remove_data->extra_comp != NULL)
+ ews_cal_append_exdate (
+ remove_data->cbews, remove_data->extra_comp, remove_data->rid,
remove_data->mod);
}
convert_error_to_edc_error (&error);
@@ -1033,51 +1071,7 @@ ews_cal_remove_object_cb (GObject *object,
g_clear_error (&error);
}
- g_free (remove_data->item_id.id);
- g_free (remove_data->item_id.change_key);
- g_object_unref (remove_data->cbews);
- if (remove_data->comp) g_object_unref (remove_data->comp);
- if (remove_data->parent) g_object_unref (remove_data->parent);
- g_object_unref (remove_data->cal);
- if (remove_data->rid) g_free (remove_data->rid);
- g_free (remove_data);
-}
-
-static guint
-e_cal_rid_to_index (ECalBackend *backend,
- const gchar *rid,
- icalcomponent *comp,
- GError **error)
-{
- guint index = 1;
- icalproperty *prop = icalcomponent_get_first_property (comp, ICAL_RRULE_PROPERTY);
- struct icalrecurrencetype rule = icalproperty_get_rrule (prop);
- struct icaltimetype dtstart = icalcomponent_get_dtstart (comp);
- icalrecur_iterator * ritr;
- icaltimetype next, o_time;
-
- /* icalcomponent_get_datetime needs a fix to initialize ret.zone to NULL. If a timezone is not
- * found in libical, it remains uninitialized in that function causing invalid read or crash. so
- * we set the timezone as we cannot identify if it has a valid timezone or not */
- dtstart.zone = e_cal_get_timezone_from_ical_component (backend, comp);
- ritr = icalrecur_iterator_new (rule, dtstart);
- next = icalrecur_iterator_next (ritr);
- o_time = icaltime_from_string (rid);
- o_time.zone = dtstart.zone;
-
- for (; !icaltime_is_null_time (next); next = icalrecur_iterator_next (ritr), index++) {
- if (icaltime_compare_date_only (o_time, next) == 0) break;
- }
-
- icalrecur_iterator_free (ritr);
-
- if (icaltime_is_null_time (next)) {
- g_propagate_error (
- error, EDC_ERROR_EX (OtherError,
- "Invalid occurrence ID"));
- }
-
- return index;
+ e_cal_backend_ews_async_data_free (remove_data);
}
static void
@@ -1089,7 +1083,7 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
const gchar *rid,
ECalObjModType mod)
{
- EwsRemoveData *remove_data;
+ EwsCalendarAsyncData *remove_data;
ECalBackendEws *cbews = (ECalBackendEws *) backend;
ECalBackendEwsPrivate *priv;
ECalComponent *comp, *parent = NULL;
@@ -1134,7 +1128,7 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
g_warning ("EEE Cant find component with uid:%s & rid:%s\n", uid, rid);
g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
PRIV_UNLOCK (priv);
- goto errorlvl1;
+ goto exit;
}
ews_cal_component_get_item_id ((comp ? comp : parent), &item_id.id, &item_id.change_key);
@@ -1145,45 +1139,54 @@ e_cal_backend_ews_remove_object (ECalBackend *backend,
g_propagate_error (
&error, EDC_ERROR_EX (OtherError,
"Cannot determine EWS ItemId"));
- goto errorlvl2;
+ goto exit;
}
if (parent && !comp) {
- index = e_cal_rid_to_index (backend, rid, e_cal_component_get_icalcomponent (parent), &error);
- if (error) goto errorlvl2;
+ index = e_cal_backend_ews_rid_to_index (
+ e_cal_backend_ews_get_timezone_from_ical_component (
+ backend,
+ e_cal_component_get_icalcomponent (comp)),
+ rid,
+ e_cal_component_get_icalcomponent (parent),
+ &error);
+
+ if (error != NULL)
+ goto exit;
}
- remove_data = g_new0 (EwsRemoveData, 1);
+ remove_data = g_new0 (EwsCalendarAsyncData, 1);
remove_data->cbews = g_object_ref (cbews);
- remove_data->comp = comp;
- remove_data->parent = parent;
+ remove_data->comp = comp != NULL ? g_object_ref (comp) : NULL;
+ remove_data->extra_comp = parent != NULL ? g_object_ref (parent) : NULL;
remove_data->cal = g_object_ref (cal);
remove_data->context = context;
- remove_data->index = index;
- remove_data->item_id.id = item_id.id;
- remove_data->item_id.change_key = item_id.change_key;
+ remove_data->item_id = g_strdup (item_id.id);
remove_data->rid = (rid ? g_strdup (rid) : NULL);
remove_data->mod = mod;
e_ews_connection_delete_item (
- priv->cnc, EWS_PRIORITY_MEDIUM, &remove_data->item_id, index,
+ priv->cnc, EWS_PRIORITY_MEDIUM, &item_id, index,
EWS_HARD_DELETE, EWS_SEND_TO_NONE, EWS_ALL_OCCURRENCES,
priv->cancellable,
ews_cal_remove_object_cb,
remove_data);
+
return;
-errorlvl2:
- if (comp) g_object_unref (comp);
+exit:
+ if (comp != NULL)
+ g_object_unref (comp);
-errorlvl1:
- if (parent) g_object_unref (parent);
+ if (parent != NULL)
+ g_object_unref (parent);
-exit:
convert_error_to_edc_error (&error);
+
if (context)
e_data_cal_respond_remove_objects (cal, context, error, NULL, NULL, NULL);
- else if (error) {
+
+ if (error != NULL) {
g_warning ("Remove object error : %s\n", error->message);
g_clear_error (&error);
}
@@ -1231,342 +1234,6 @@ e_cal_backend_ews_remove_objects (ECalBackend *backend,
static icaltimezone * resolve_tzid (const gchar *tzid, gpointer user_data);
static void put_component_to_store (ECalBackendEws *cbews,ECalComponent *comp);
-typedef struct {
- ECalBackendEws *cbews;
- EDataCal *cal;
- ECalComponent *comp;
- guint32 context;
-} EwsCreateData;
-
-typedef struct {
- ECalBackendEws *cbews;
- icalcomponent *icalcomp;
-} EwsConvertData;
-
-static void
-add_attendees_list_to_message (ESoapMessage *msg,
- const gchar *listname,
- GSList *list)
-{
- GSList *item;
-
- e_soap_message_start_element (msg, listname, NULL, NULL);
-
- for (item = list; item != NULL; item = item->next) {
- e_soap_message_start_element (msg, "Attendee", NULL, NULL);
- e_soap_message_start_element (msg, "Mailbox", NULL, NULL);
-
- e_ews_message_write_string_parameter (msg, "EmailAddress", NULL, item->data);
-
- e_soap_message_end_element (msg); /* "Mailbox" */
- e_soap_message_end_element (msg); /* "Attendee" */
- }
-
- e_soap_message_end_element (msg);
-}
-
-static void
-convert_sensitivity_calcomp_to_xml (ESoapMessage *msg,
- icalcomponent *icalcomp)
-{
- icalproperty *prop;
-
- g_return_if_fail (msg != NULL);
- g_return_if_fail (icalcomp != NULL);
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
- if (prop) {
- icalproperty_class classify = icalproperty_get_class (prop);
- if (classify == ICAL_CLASS_PUBLIC) {
- e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Normal");
- } else if (classify == ICAL_CLASS_PRIVATE) {
- e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Private");
- } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
- e_ews_message_write_string_parameter (msg, "Sensitivity", NULL, "Personal");
- }
- }
-}
-
-static void
-convert_categories_calcomp_to_xml (ESoapMessage *msg,
- ECalComponent *comp,
- icalcomponent *icalcomp)
-{
- GSList *categ_list, *citer;
-
- g_return_if_fail (msg != NULL);
- g_return_if_fail (icalcomp != NULL);
-
- if (comp) {
- g_object_ref (comp);
- } else {
- icalcomponent *clone = icalcomponent_new_clone (icalcomp);
-
- comp = e_cal_component_new ();
- if (!e_cal_component_set_icalcomponent (comp, clone)) {
- icalcomponent_free (clone);
- g_object_unref (comp);
-
- return;
- }
- }
-
- e_cal_component_get_categories_list (comp, &categ_list);
-
- g_object_unref (comp);
-
- if (!categ_list)
- return;
-
- e_soap_message_start_element (msg, "Categories", NULL, NULL);
-
- for (citer = categ_list; citer; citer = g_slist_next (citer)) {
- const gchar *category = citer->data;
-
- if (!category || !*category)
- continue;
-
- e_ews_message_write_string_parameter (msg, "String", NULL, category);
- }
-
- e_soap_message_end_element (msg); /* Categories */
-
- e_cal_component_free_categories_list (categ_list);
-}
-
-static void
-convert_vevent_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsConvertData *convert_data = user_data;
- icalcomponent *icalcomp = convert_data->icalcomp;
- ECalComponent *comp = e_cal_component_new ();
- GSList *required = NULL, *optional = NULL, *resource = NULL;
- icaltimetype dtstart, dtend;
- icalproperty *prop;
- gboolean has_alarms;
- const gchar *value;
-
- e_cal_component_set_icalcomponent (comp, icalcomp);
-
- /* FORMAT OF A SAMPLE SOAP MESSAGE: http://msdn.microsoft.com/en-us/library/aa564690.aspx */
-
- /* Prepare CalendarItem node in the SOAP message */
- e_soap_message_start_element (msg, "CalendarItem", NULL, NULL);
-
- /* subject */
- value = icalcomponent_get_summary (icalcomp);
- if (value)
- e_ews_message_write_string_parameter (msg, "Subject", NULL, value);
-
- convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
- /* description */
- value = icalcomponent_get_description (icalcomp);
- if (value)
- e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, value, "BodyType",
"Text");
-
- convert_categories_calcomp_to_xml (msg, comp, icalcomp);
-
- /* set alarms */
- has_alarms = e_cal_component_has_alarms (comp);
- if (has_alarms)
- ews_set_alarm (msg, comp);
- else
- e_ews_message_write_string_parameter (msg, "ReminderIsSet", NULL, "false");
-
- /* start time, end time and meeting time zone */
- dtstart = icalcomponent_get_dtstart (icalcomp);
- dtend = icalcomponent_get_dtend (icalcomp);
-
- ewscal_set_time (msg, "Start", &dtstart, FALSE);
- ewscal_set_time (msg, "End", &dtend, FALSE);
- /* We have to do the time zone(s) later, or the server rejects the request */
-
- /* All day event ? */
- if (icaltime_is_date (dtstart))
- e_ews_message_write_string_parameter (msg, "IsAllDayEvent", NULL, "true");
-
- /*freebusy*/
- prop = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
- if (!g_strcmp0 (icalproperty_get_value_as_string (prop), "TRANSPARENT"))
- e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Free");
- else
- e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus",NULL,"Busy");
-
- /* location */
- value = icalcomponent_get_location (icalcomp);
- if (value)
- e_ews_message_write_string_parameter (msg, "Location", NULL, value);
-
- /* collect attendees */
- e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
-
- if (required != NULL) {
- add_attendees_list_to_message (msg, "RequiredAttendees", required);
- g_slist_free (required);
- }
- if (optional != NULL) {
- add_attendees_list_to_message (msg, "OptionalAttendees", optional);
- g_slist_free (optional);
- }
- if (resource != NULL) {
- add_attendees_list_to_message (msg, "Resources", resource);
- g_slist_free (resource);
- }
- /* end of attendees */
-
- /* Recurrence */
- prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
- if (prop != NULL) {
- ewscal_set_reccurence (msg, prop, &dtstart);
- }
-
- if (0 /* Exchange 2010 detected */ && dtstart.zone != dtend.zone) {
- /* We have to cast these because libical puts a const pointer into the
- * icaltimetype, but its basic read-only icaltimezone_foo() functions
- * take a non-const pointer! */
- ewscal_set_timezone (msg, "StartTimeZone", (icaltimezone *) dtstart.zone);
- ewscal_set_timezone (msg, "EndTimeZone", (icaltimezone *) dtstart.zone);
- } else
- ewscal_set_timezone (msg, "MeetingTimeZone", (icaltimezone *)(dtstart.zone ? dtstart.zone :
convert_data->cbews->priv->default_zone));
-
- // end of "CalendarItem"
- e_soap_message_end_element (msg);
-}
-
-static void
-convert_vtodo_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsConvertData *convert_data = user_data;
- icalcomponent *icalcomp = convert_data->icalcomp;
- icalproperty *prop;
- icaltimetype dt;
- gint value;
- gchar buffer[16];
-
- e_soap_message_start_element (msg, "Task", NULL, NULL);
-
- e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
-
- convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
- e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, icalcomponent_get_description
(icalcomp), "BodyType", "Text");
-
- convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
- if (prop) {
- dt = icalproperty_get_due (prop);
- ewscal_set_time (msg, "DueDate", &dt, TRUE);
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
- if (prop) {
- value = icalproperty_get_percentcomplete (prop);
- snprintf (buffer, 16, "%d", value);
- e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
- if (prop) {
- dt = icalproperty_get_dtstart (prop);
- ewscal_set_time (msg, "StartDate", &dt, TRUE);
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
- if (prop) {
- switch (icalproperty_get_status (prop)) {
- case ICAL_STATUS_INPROCESS:
- e_ews_message_write_string_parameter (msg, "Status", NULL, "InProgress");
- break;
- case ICAL_STATUS_COMPLETED:
- e_ews_message_write_string_parameter (msg, "Status", NULL, "Completed");
- break;
- default:
- break;
- }
- }
-
- e_soap_message_end_element (msg); // "Task"
-}
-
-static void
-convert_vjournal_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsConvertData *convert_data = user_data;
- icalcomponent *icalcomp = convert_data->icalcomp;
- const gchar *text;
-
- e_soap_message_start_element (msg, "Message", NULL, NULL);
- e_ews_message_write_string_parameter (msg, "ItemClass", NULL, "IPM.StickyNote");
-
- e_ews_message_write_string_parameter (msg, "Subject", NULL, icalcomponent_get_summary (icalcomp));
-
- convert_sensitivity_calcomp_to_xml (msg, icalcomp);
-
- text = icalcomponent_get_description (icalcomp);
- if (!text || !*text)
- text = icalcomponent_get_summary (icalcomp);
- e_ews_message_write_string_parameter_with_attribute (msg, "Body", NULL, text, "BodyType", "Text");
-
- convert_categories_calcomp_to_xml (msg, NULL, icalcomp);
-
- e_soap_message_end_element (msg); /* Message */
-}
-
-static void
-convert_calcomp_to_xml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsConvertData *convert_data = user_data;
-
- switch (icalcomponent_isa (convert_data->icalcomp)) {
- case ICAL_VEVENT_COMPONENT:
- convert_vevent_calcomp_to_xml (msg, user_data);
- break;
- case ICAL_VTODO_COMPONENT:
- convert_vtodo_calcomp_to_xml (msg, user_data);
- break;
- case ICAL_VJOURNAL_COMPONENT:
- convert_vjournal_calcomp_to_xml (msg, user_data);
- break;
- default:
- g_warn_if_reached ();
- break;
- }
-
- g_object_unref (convert_data->cbews);
- g_free (convert_data);
-}
-
-/*I will unate both type, they are same now*/
-typedef struct {
- ECalBackendEws *cbews;
- ECalComponent *comp;
- gint cb_type; /* 0 - nothing,
- 1 - create,
- 2 - update */
- EDataCal *cal;
- guint32 context;
- ECalComponent *oldcomp;
- gchar *itemid;
- gchar *changekey;
-
-} EwsAttachmentsData;
-
-typedef struct {
- ECalBackendEws *cbews;
- EDataCal *cal;
- ECalComponent *comp;
- ECalComponent *oldcomp;
- guint32 context;
- gchar *itemid;
- gchar *changekey;
-} EwsModifyData;
-
static void
e_cal_backend_ews_modify_object (ECalBackend *backend,
EDataCal *cal,
@@ -1575,8 +1242,6 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
const gchar *calobj,
ECalObjModType mod);
-static void convert_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data);
static void ews_cal_modify_object_cb (GObject *object,
GAsyncResult *res,
gpointer user_data);
@@ -1587,7 +1252,7 @@ ews_create_attachments_cb (GObject *object,
gpointer user_data)
{
EEwsConnection *cnc = E_EWS_CONNECTION (object);
- EwsAttachmentsData *create_data = user_data;
+ EwsCalendarAsyncData *create_data = user_data;
ECalBackendEwsPrivate *priv = create_data->cbews->priv;
gchar *change_key;
GSList *ids, *i;
@@ -1635,26 +1300,27 @@ ews_create_attachments_cb (GObject *object,
e_cal_backend_store_thaw_changes (priv->store);
e_cal_component_get_uid (create_data->comp, &comp_uid);
- if (create_data->cb_type == 1) {
- /*In case we have attendees we have to fake update items,
- * this is the only way to pass attachments in meeting invite mail*/
- if (e_cal_component_has_attendees (create_data->comp)) {
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (create_data->comp);
- e_cal_backend_ews_modify_object ((ECalBackend *) create_data->cbews,
create_data->cal, 0, NULL, icalcomponent_as_ical_string (icalcomp), E_CAL_OBJ_MOD_ALL);
- }
- } else if (create_data->cb_type == 2) {
+ if (create_data->cb_type == E_EWS_ATTACHMENT_TYPE_UPDATE) {
const gchar *send_meeting_invitations;
const gchar *send_or_save;
- EwsModifyData * modify_data;
+ EwsCalendarAsyncData *modify_data;
+ EwsCalendarConvertData convert_data;
- modify_data = g_new0 (EwsModifyData, 1);
+ modify_data = g_new0 (EwsCalendarAsyncData, 1);
modify_data->cbews = g_object_ref (create_data->cbews);
- modify_data->comp = create_data->comp;
- modify_data->oldcomp = create_data->oldcomp;
+ modify_data->comp = g_object_ref (create_data->comp);
+ modify_data->extra_comp = g_object_ref (create_data->extra_comp);
modify_data->cal = g_object_ref (create_data->cal);
modify_data->context = create_data->context;
- modify_data->itemid = create_data->itemid;
- modify_data->changekey = change_key;
+ modify_data->item_id = create_data->item_id;
+
+ convert_data.connection = create_data->cbews->priv->cnc;
+ convert_data.user_email = create_data->cbews->priv->user_email;
+ convert_data.comp = create_data->comp;
+ convert_data.old_comp = create_data->extra_comp;
+ convert_data.item_id = create_data->item_id;
+ convert_data.change_key = change_key;
+ convert_data.default_zone = create_data->cbews->priv->default_zone;
if (e_cal_component_has_attendees (create_data->comp)) {
send_meeting_invitations = "SendToAllAndSaveCopy";
@@ -1671,20 +1337,30 @@ ews_create_attachments_cb (GObject *object,
send_or_save,
send_meeting_invitations,
priv->folder_id,
- convert_component_to_updatexml,
- modify_data,
+ e_cal_backend_ews_convert_component_to_updatexml,
+ &convert_data,
priv->cancellable,
ews_cal_modify_object_cb,
modify_data);
+ } else {
+ if (create_data->cb_type == E_EWS_ATTACHMENT_TYPE_CREATE) {
+ /*In case we have attendees we have to fake update items,
+ * this is the only way to pass attachments in meeting invite mail*/
+ if (e_cal_component_has_attendees (create_data->comp)) {
+ icalcomponent *icalcomp = e_cal_component_get_icalcomponent
(create_data->comp);
+ e_cal_backend_ews_modify_object (
+ E_CAL_BACKEND (create_data->cbews),
+ create_data->cal,
+ 0,
+ NULL,
+ icalcomponent_as_ical_string (icalcomp),
+ E_CAL_OBJ_MOD_ALL);
+ }
+ }
}
+ e_cal_backend_ews_async_data_free (create_data);
g_slist_free (ids);
-
- g_object_unref (create_data->cbews);
- g_object_unref (create_data->cal);
- g_object_unref (create_data->comp);
- if (create_data->oldcomp) g_object_unref (create_data->oldcomp);
- g_free (create_data);
}
static void
@@ -1693,7 +1369,7 @@ ews_create_object_cb (GObject *object,
gpointer user_data)
{
EEwsConnection *cnc = E_EWS_CONNECTION (object);
- EwsCreateData *create_data = user_data;
+ EwsCalendarAsyncData *create_data = user_data;
ECalBackendEws *cbews = create_data->cbews;
ECalBackendEwsPrivate *priv = cbews->priv;
GError *error = NULL;
@@ -1763,7 +1439,7 @@ ews_create_object_cb (GObject *object,
n_attach = e_cal_component_get_num_attachments (create_data->comp);
if (n_attach > 0) {
GSList *info_attachments = NULL;
- EwsAttachmentsData *attach_data = g_new0 (EwsAttachmentsData, 1);
+ EwsCalendarAsyncData *attach_data = g_new0 (EwsCalendarAsyncData, 1);
attach_data->cbews = g_object_ref (create_data->cbews);
attach_data->comp = g_object_ref (create_data->comp);
@@ -1853,13 +1529,7 @@ ews_create_object_cb (GObject *object,
g_slist_free_full (exceptions, g_free);
}
- /* no need to keep reference to the object */
- g_object_unref (create_data->comp);
-
- /* free memory allocated for create_data & unref contained objects */
- g_object_unref (create_data->cbews);
- g_object_unref (create_data->cal);
- g_free (create_data);
+ e_cal_backend_ews_async_data_free (create_data);
}
struct TzidCbData {
@@ -1890,14 +1560,28 @@ static void tzid_cb (icalparameter *param, gpointer data)
}
static void
+e_cal_backend_ews_pick_all_tzids_out (ECalBackendEws *cbews,
+ icalcomponent *icalcomp)
+{
+
+ /* pick all the tzids out of the component and resolve
+ * them using the vtimezones in the current calendar */
+ struct TzidCbData cbd;
+
+ cbd.cbews = cbews;
+ cbd.comp = icalcomp;
+ icalcomponent_foreach_tzid (icalcomp, tzid_cb, &cbd);
+}
+
+static void
e_cal_backend_ews_create_objects (ECalBackend *backend,
EDataCal *cal,
guint32 context,
GCancellable *cancellable,
const GSList *calobjs)
{
- EwsCreateData *create_data;
- EwsConvertData *convert_data;
+ EwsCalendarAsyncData *create_data;
+ EwsCalendarConvertData convert_data;
EwsFolderId *fid;
ECalBackendEws *cbews;
ECalBackendEwsPrivate *priv;
@@ -1907,7 +1591,6 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
struct icaltimetype current;
GError *error = NULL;
const gchar *send_meeting_invitations, *calobj;
- struct TzidCbData cbd;
/* sanity check */
e_data_cal_error_if_fail (E_IS_CAL_BACKEND_EWS (backend), InvalidArg);
@@ -1937,7 +1620,7 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
}
/* parse ical data */
- comp = e_cal_component_new_from_string (calobj);
+ comp = e_cal_component_new_from_string (calobj);
if (comp == NULL) {
g_propagate_error (&error, EDC_ERROR (InvalidObject));
goto exit;
@@ -1958,40 +1641,41 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
}
e_ews_clean_icalcomponent (icalcomp);
- /* pick all the tzids out of the component and resolve
- * them using the vtimezones in the current calendar */
- cbd.cbews = cbews;
- cbd.comp = icalcomp;
- icalcomponent_foreach_tzid (icalcomp, tzid_cb, &cbd);
+
+ if (!e_ews_connection_satisfies_server_version (cbews->priv->cnc, E_EWS_EXCHANGE_2010))
+ e_cal_backend_ews_pick_all_tzids_out (cbews, icalcomp);
/* prepare new calender component */
current = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
e_cal_component_set_created (comp, ¤t);
e_cal_component_set_last_modified (comp, ¤t);
- create_data = g_new0 (EwsCreateData, 1);
+ create_data = g_new0 (EwsCalendarAsyncData, 1);
create_data->cbews = g_object_ref (cbews);
- create_data->comp = comp;
+ create_data->comp = g_object_ref (comp);
create_data->cal = g_object_ref (cal);
create_data->context = context;
- convert_data = g_new0 (EwsConvertData, 1);
- convert_data->cbews = g_object_ref (cbews);
- convert_data->icalcomp = icalcomp;
+ convert_data.connection = cbews->priv->cnc;
+ convert_data.icalcomp = icalcomp;
+ convert_data.default_zone = cbews->priv->default_zone;
- /*In case we are creating a meeting with attendees and attachments.
+ /*
+ * In case we are creating a meeting with attendees and attachments.
* We have to preform 3 steps in order to allow attendees to receive attachments in their invite
mails.
* 1. create meeting and do not send invites
* 2. create attachments
- * 3. dummy update meeting and send invites to all*/
+ * 3. dummy update meeting and send invites to all
+ */
if (e_cal_component_has_attendees (comp)) {
if (e_cal_component_has_attachments (comp))
send_meeting_invitations = "SendToNone";
else
send_meeting_invitations = "SendToAllAndSaveCopy";
- } else
+ } else {
/*In case of appointment we have to set SendMeetingInvites to SendToNone */
send_meeting_invitations = "SendToNone";
+ }
fid = e_ews_folder_id_new (priv->folder_id, NULL, FALSE);
@@ -2001,8 +1685,8 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
"SaveOnly",
send_meeting_invitations,
fid,
- convert_calcomp_to_xml,
- convert_data,
+ e_cal_backend_ews_convert_calcomp_to_xml,
+ &convert_data,
cancellable,
ews_create_object_cb,
create_data);
@@ -2012,6 +1696,9 @@ e_cal_backend_ews_create_objects (ECalBackend *backend,
return;
exit:
+ if (comp != NULL)
+ g_object_unref (comp);
+
convert_error_to_edc_error (&error);
e_data_cal_respond_create_objects (cal, context, error, NULL, NULL);
}
@@ -2022,7 +1709,7 @@ ews_cal_modify_object_cb (GObject *object,
gpointer user_data)
{
EEwsConnection *cnc = E_EWS_CONNECTION (object);
- EwsModifyData *modify_data = user_data;
+ EwsCalendarAsyncData *modify_data = user_data;
ECalBackendEws *cbews = modify_data->cbews;
ECalBackendEwsPrivate *priv = cbews->priv;
GError *error = NULL;
@@ -2040,9 +1727,6 @@ ews_cal_modify_object_cb (GObject *object,
goto exit;
}
- g_object_ref (modify_data->comp);
- g_object_ref (modify_data->oldcomp);
-
e_cal_backend_store_freeze_changes (priv->store);
item_id = e_ews_item_get_id ((EEwsItem *) ids->data);
@@ -2067,9 +1751,9 @@ ews_cal_modify_object_cb (GObject *object,
if (modify_data->context) {
GSList *old_components, *new_components;
- e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbews), modify_data->oldcomp,
modify_data->comp);
+ e_cal_backend_notify_component_modified (E_CAL_BACKEND (cbews), modify_data->extra_comp,
modify_data->comp);
- old_components = g_slist_append (NULL, modify_data->oldcomp);
+ old_components = g_slist_append (NULL, modify_data->extra_comp);
new_components = g_slist_append (NULL, modify_data->comp);
convert_error_to_edc_error (&error);
@@ -2077,14 +1761,15 @@ ews_cal_modify_object_cb (GObject *object,
g_slist_free (old_components);
g_slist_free (new_components);
- }
- else if (error) {
+ } else if (error != NULL) {
g_warning ("Modify object error : %s\n", error->message);
g_clear_error (&error);
- } else ews_start_sync (modify_data->cbews);
+ } else {
+ ews_start_sync (cbews);
+ }
PRIV_LOCK (priv);
- g_hash_table_replace (priv->item_id_hash, g_strdup (modify_data->itemid), g_object_ref
(modify_data->comp));
+ g_hash_table_replace (priv->item_id_hash, g_strdup (modify_data->item_id), g_object_ref
(modify_data->comp));
PRIV_UNLOCK (priv);
e_cal_backend_store_thaw_changes (priv->store);
@@ -2093,427 +1778,7 @@ ews_cal_modify_object_cb (GObject *object,
e_cal_component_free_id (id);
exit:
- g_free (modify_data->itemid);
- g_free (modify_data->changekey);
- g_object_unref (modify_data->comp);
- g_object_unref (modify_data->oldcomp);
- g_object_unref (modify_data->cbews);
- g_object_unref (modify_data->cal);
- g_free (modify_data);
-}
-
-static void
-convert_component_categories_to_updatexml (ECalComponent *comp,
- ESoapMessage *msg,
- const gchar *base_elem_name)
-{
- GSList *categ_list = NULL, *citer;
-
- g_return_if_fail (comp != NULL);
- g_return_if_fail (msg != NULL);
- g_return_if_fail (base_elem_name != NULL);
-
- e_cal_component_get_categories_list (comp, &categ_list);
- e_ews_message_start_set_item_field (msg, "Categories", "item", base_elem_name);
- e_soap_message_start_element (msg, "Categories", NULL, NULL);
-
- for (citer = categ_list; citer; citer = g_slist_next (citer)) {
- const gchar *category = citer->data;
-
- if (!category || !*category)
- continue;
-
- e_ews_message_write_string_parameter (msg, "String", NULL, category);
- }
-
- e_soap_message_end_element (msg); /* Categories */
- e_ews_message_end_set_item_field (msg);
-
- e_cal_component_free_categories_list (categ_list);
-}
-
-static void
-convert_vevent_property_to_updatexml (ESoapMessage *msg,
- const gchar *name,
- const gchar *value,
- const gchar *prefix,
- const gchar *attr_name,
- const gchar *attr_value)
-{
- e_ews_message_start_set_item_field (msg, name, prefix, "CalendarItem");
- e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
- e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vevent_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsModifyData *modify_data = user_data;
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
- icalcomponent *icalcomp_old = e_cal_component_get_icalcomponent (modify_data->oldcomp);
- GSList *required = NULL, *optional = NULL, *resource = NULL;
- icaltimetype dtstart, dtend, dtstart_old, dtend_old;
- icalproperty *prop, *transp;
- const gchar *org_email_address = NULL, *value = NULL, *old_value = NULL;
- gboolean has_alarms, has_alarms_old, dt_changed = FALSE;
- 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) {
- /* A single occurrence ? */
- prop = icalcomponent_get_first_property (icalcomp, ICAL_RECURRENCEID_PROPERTY);
- if (prop != NULL) {
- recid = icalproperty_get_value_as_string_r (prop);
- e_ews_message_start_item_change (
- msg, E_EWS_ITEMCHANGE_TYPE_OCCURRENCEITEM,
- modify_data->itemid, modify_data->changekey, e_cal_rid_to_index
(E_CAL_BACKEND (modify_data->cbews), recid, icalcomp_old, &error));
- free (recid);
- } else {
- e_ews_message_start_item_change (
- msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
- modify_data->itemid, modify_data->changekey, 0);
- }
- } else e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
- modify_data->itemid, modify_data->changekey, 0);
-
- /* subject */
- value = icalcomponent_get_summary (icalcomp);
- old_value = icalcomponent_get_summary (icalcomp_old);
- if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
- (value && old_value == NULL)) {
- convert_vevent_property_to_updatexml (msg, "Subject", value, "item", NULL, NULL);
- } else if (!value && old_value)
- convert_vevent_property_to_updatexml (msg, "Subject", "", "item", NULL, NULL);
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
- if (prop) {
- icalproperty_class classify = icalproperty_get_class (prop);
- if (classify == ICAL_CLASS_PUBLIC) {
- convert_vevent_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_PRIVATE) {
- convert_vevent_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
- convert_vevent_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
- }
- }
-
- /*description*/
- value = icalcomponent_get_description (icalcomp);
- old_value = icalcomponent_get_description (icalcomp_old);
- if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
- (value && old_value == NULL)) {
- convert_vevent_property_to_updatexml (msg, "Body", value, "item", "BodyType", "Text");
- } else if (!value && old_value)
- convert_vevent_property_to_updatexml (msg, "Body", "", "item", "BodyType", "Text");
-
- /*update alarm items*/
- has_alarms = e_cal_component_has_alarms (modify_data->comp);
- if (has_alarms) {
- alarm = ews_get_alarm (modify_data->comp);
- has_alarms_old = e_cal_component_has_alarms (modify_data->oldcomp);
- if (has_alarms_old)
- alarm_old = ews_get_alarm (modify_data->oldcomp);
- if (!(alarm == alarm_old)) {
- gchar buf[20];
- snprintf (buf, 20, "%d", alarm);
- convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "true", "item", NULL,
NULL);
- convert_vevent_property_to_updatexml (msg, "ReminderMinutesBeforeStart", buf, "item",
NULL, NULL);
- }
- }
- else convert_vevent_property_to_updatexml (msg, "ReminderIsSet", "false", "item", NULL, NULL);
-
- /* Categories */
- convert_component_categories_to_updatexml (modify_data->comp, msg, "CalendarItem");
-
- /*location*/
- value = icalcomponent_get_location (icalcomp);
- old_value = icalcomponent_get_location (icalcomp_old);
- if ((value && old_value && g_ascii_strcasecmp (value, old_value)) ||
- (value && old_value == NULL)) {
- convert_vevent_property_to_updatexml (msg, "Location", value, "calendar", NULL, NULL);
- } else if (!value && old_value)
- convert_vevent_property_to_updatexml (msg, "Location", "", "calendar", NULL, NULL);
-
- /*freebusy*/
- transp = icalcomponent_get_first_property (icalcomp, ICAL_TRANSP_PROPERTY);
- value = icalproperty_get_value_as_string (transp);
- transp = icalcomponent_get_first_property (icalcomp_old, ICAL_TRANSP_PROPERTY);
- old_value = icalproperty_get_value_as_string (transp);
- if (g_strcmp0 (value, old_value)) {
- if (!g_strcmp0 (value, "TRANSPARENT"))
- convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Free" ,
"calendar", NULL, NULL);
- else
- convert_vevent_property_to_updatexml (msg, "LegacyFreeBusyStatus","Busy" ,
"calendar", NULL, NULL);
- }
-
- org_email_address = e_ews_collect_organizer (icalcomp);
- if (org_email_address && g_ascii_strcasecmp (org_email_address,
modify_data->cbews->priv->user_email)) {
- e_ews_message_end_item_change (msg);
- return;
- }
- /* Update other properties allowed only for meeting organizers*/
- /*meeting dates*/
- dtstart = icalcomponent_get_dtstart (icalcomp);
- dtend = icalcomponent_get_dtend (icalcomp);
- dtstart_old = icalcomponent_get_dtstart (icalcomp_old);
- dtend_old = icalcomponent_get_dtend (icalcomp_old);
- if (icaltime_compare (dtstart, dtstart_old) != 0) {
- e_ews_message_start_set_item_field (msg, "Start", "calendar","CalendarItem");
- ewscal_set_time (msg, "Start", &dtstart, FALSE);
- e_ews_message_end_set_item_field (msg);
- dt_changed = TRUE;
- }
-
- if (icaltime_compare (dtend, dtend_old) != 0) {
- e_ews_message_start_set_item_field (msg, "End", "calendar", "CalendarItem");
- ewscal_set_time (msg, "End", &dtend, FALSE);
- e_ews_message_end_set_item_field (msg);
- dt_changed = TRUE;
- }
-
- /*Check for All Day Event*/
- if (dt_changed) {
- if (icaltime_is_date (dtstart))
- convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "true", "calendar", NULL,
NULL);
- else
- convert_vevent_property_to_updatexml (msg, "IsAllDayEvent", "false", "calendar",
NULL, NULL);
- }
-
- /*need to test it*/
- e_ews_collect_attendees (icalcomp, &required, &optional, &resource);
- if (required != NULL) {
- e_ews_message_start_set_item_field (msg, "RequiredAttendees", "calendar", "CalendarItem");
-
- add_attendees_list_to_message (msg, "RequiredAttendees", required);
- g_slist_free (required);
-
- e_ews_message_end_set_item_field (msg);
- }
- if (optional != NULL) {
- e_ews_message_start_set_item_field (msg, "OptionalAttendees", "calendar", "CalendarItem");
-
- add_attendees_list_to_message (msg, "OptionalAttendees", optional);
- g_slist_free (optional);
-
- e_ews_message_end_set_item_field (msg);
- }
- if (resource != NULL) {
- e_ews_message_start_set_item_field (msg, "Resources", "calendar", "CalendarItem");
-
- add_attendees_list_to_message (msg, "Resources", resource);
- g_slist_free (resource);
-
- e_ews_message_end_set_item_field (msg);
- }
-
- /* Recurrence */
- value = NULL; old_value = NULL;
- prop = icalcomponent_get_first_property (icalcomp_old, ICAL_RRULE_PROPERTY);
- if (prop != NULL)
- old_value = icalproperty_get_value_as_string (prop);
- prop = icalcomponent_get_first_property (icalcomp, ICAL_RRULE_PROPERTY);
- if (prop != NULL)
- value = icalproperty_get_value_as_string (prop);
-
- if (prop != NULL && g_strcmp0 (value, old_value)) {
- e_ews_message_start_set_item_field (msg, "Recurrence", "calendar", "CalendarItem");
- ewscal_set_reccurence (msg, prop, &dtstart);
- e_ews_message_end_set_item_field (msg);
- }
-
- if (0 /* Exchange 2010 detected */ && dtstart.zone != dtend.zone) {
- if (dtstart.zone) {
- e_ews_message_start_set_item_field (msg, "StartTimeZone", "calendar", "CalendarItem");
- ewscal_set_timezone (msg, "StartTimeZone", (icaltimezone *) dtstart.zone);
- e_ews_message_end_set_item_field (msg);
- }
- if (dtend.zone) {
- e_ews_message_start_set_item_field (msg, "EndTimeZone", "calendar", "CalendarItem");
- ewscal_set_timezone (msg, "EndTimeZone", (icaltimezone *) dtend.zone);
- e_ews_message_end_set_item_field (msg);
- }
- } else {
- e_ews_message_start_set_item_field (msg, "MeetingTimeZone", "calendar", "CalendarItem");
- ewscal_set_timezone (msg, "MeetingTimeZone", (icaltimezone *)(dtstart.zone ? dtstart.zone :
modify_data->cbews->priv->default_zone));
- e_ews_message_end_set_item_field (msg);
- }
-
- e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_vtodo_property_to_updatexml (ESoapMessage *msg,
- const gchar *name,
- const gchar *value,
- const gchar *prefix,
- const gchar *attr_name,
- const gchar *attr_value)
-{
- e_ews_message_start_set_item_field (msg, name, prefix, "Task");
- e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
- e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vtodo_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsModifyData *modify_data = user_data;
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
- icalproperty *prop;
- icaltimetype dt;
- gint value;
- gchar buffer[16];
-
- e_ews_message_start_item_change (
- msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
- modify_data->itemid, modify_data->changekey, 0);
-
- convert_vtodo_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item",
NULL, NULL);
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
- if (prop) {
- icalproperty_class classify = icalproperty_get_class (prop);
- if (classify == ICAL_CLASS_PUBLIC) {
- convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_PRIVATE) {
- convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
- convert_vtodo_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
- }
- }
-
- convert_vtodo_property_to_updatexml (msg, "Body", icalcomponent_get_description (icalcomp), "item",
"BodyType", "Text");
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_DUE_PROPERTY);
- if (prop) {
- dt = icalproperty_get_due (prop);
- e_ews_message_start_set_item_field (msg, "DueDate", "task", "Task");
- ewscal_set_time (msg, "DueDate", &dt, TRUE);
- e_ews_message_end_set_item_field (msg);
- } else {
- e_ews_message_add_delete_item_field (msg, "DueDate", "task");
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_PERCENTCOMPLETE_PROPERTY);
- if (prop) {
- value = icalproperty_get_percentcomplete (prop);
- snprintf (buffer, 16, "%d", value);
- e_ews_message_start_set_item_field (msg, "PercentComplete", "task", "Task");
- e_ews_message_write_string_parameter (msg, "PercentComplete", NULL, buffer);
- e_ews_message_end_set_item_field (msg);
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_DTSTART_PROPERTY);
- if (prop) {
- dt = icalproperty_get_dtstart (prop);
- e_ews_message_start_set_item_field (msg, "StartDate", "task", "Task");
- ewscal_set_time (msg, "StartDate", &dt, TRUE);
- e_ews_message_end_set_item_field (msg);
- } else {
- e_ews_message_add_delete_item_field (msg, "StartDate", "task");
- }
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_STATUS_PROPERTY);
- if (prop) {
- switch (icalproperty_get_status (prop)) {
- case ICAL_STATUS_INPROCESS:
- convert_vtodo_property_to_updatexml (msg, "Status", "InProgress", "task", NULL, NULL);
- break;
- case ICAL_STATUS_COMPLETED:
- convert_vtodo_property_to_updatexml (msg, "Status", "Completed", "task", NULL, NULL);
- break;
- case ICAL_STATUS_NONE:
- case ICAL_STATUS_NEEDSACTION:
- convert_vtodo_property_to_updatexml (msg, "Status", "NotStarted", "task", NULL, NULL);
- break;
- default:
- break;
- }
- }
-
- /* Categories */
- convert_component_categories_to_updatexml (modify_data->comp, msg, "Task");
-
- e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_vjournal_property_to_updatexml (ESoapMessage *msg,
- const gchar *name,
- const gchar *value,
- const gchar *prefix,
- const gchar *attr_name,
- const gchar *attr_value)
-{
- e_ews_message_start_set_item_field (msg, name, prefix, "Message");
- e_ews_message_write_string_parameter_with_attribute (msg, name, NULL, value, attr_name, attr_value);
- e_ews_message_end_set_item_field (msg);
-}
-
-static void
-convert_vjournal_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsModifyData *modify_data = user_data;
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
- icalproperty *prop;
- const gchar *text;
-
- e_ews_message_start_item_change (
- msg, E_EWS_ITEMCHANGE_TYPE_ITEM,
- modify_data->itemid, modify_data->changekey, 0);
-
- convert_vjournal_property_to_updatexml (msg, "ItemClass", "IPM.StickyNote", "item", NULL, NULL);
- convert_vjournal_property_to_updatexml (msg, "Subject", icalcomponent_get_summary (icalcomp), "item",
NULL, NULL);
-
- prop = icalcomponent_get_first_property (icalcomp, ICAL_CLASS_PROPERTY);
- if (prop) {
- icalproperty_class classify = icalproperty_get_class (prop);
- if (classify == ICAL_CLASS_PUBLIC) {
- convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Normal", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_PRIVATE) {
- convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Private", "item", NULL,
NULL);
- } else if (classify == ICAL_CLASS_CONFIDENTIAL) {
- convert_vjournal_property_to_updatexml (msg, "Sensitivity", "Personal", "item", NULL,
NULL);
- }
- }
-
- text = icalcomponent_get_description (icalcomp);
- if (!text || !*text)
- text = icalcomponent_get_summary (icalcomp);
-
- convert_vjournal_property_to_updatexml (msg, "Body", text, "item", "BodyType", "Text");
-
- /* Categories */
- convert_component_categories_to_updatexml (modify_data->comp, msg, "Message");
-
- e_ews_message_end_item_change (msg);
-}
-
-static void
-convert_component_to_updatexml (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsModifyData *modify_data = user_data;
- icalcomponent *icalcomp = e_cal_component_get_icalcomponent (modify_data->comp);
-
- switch (icalcomponent_isa (icalcomp)) {
- case ICAL_VEVENT_COMPONENT:
- convert_vevent_component_to_updatexml (msg, user_data);
- break;
- case ICAL_VTODO_COMPONENT:
- convert_vtodo_component_to_updatexml (msg, user_data);
- break;
- case ICAL_VJOURNAL_COMPONENT:
- convert_vjournal_component_to_updatexml (msg, user_data);
- break;
- default:
- break;
- }
+ e_cal_backend_ews_async_data_free (modify_data);
}
static void
@@ -2553,7 +1818,7 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
const gchar *calobj,
ECalObjModType mod)
{
- EwsModifyData *modify_data;
+ EwsCalendarAsyncData *modify_data;
ECalBackendEws *cbews;
ECalBackendEwsPrivate *priv;
icalcomponent_kind kind;
@@ -2563,8 +1828,7 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
struct icaltimetype current;
GError *error = NULL;
GSList *original_attachments = NULL, *modified_attachments = NULL, *added_attachments = NULL,
*removed_attachments = NULL, *removed_attachments_ids = NULL, *i;
- EwsAttachmentsData *attach_data;
- struct TzidCbData cbd;
+ EwsCalendarAsyncData *attach_data;
e_data_cal_error_if_fail (E_IS_CAL_BACKEND_EWS (backend), InvalidArg);
e_data_cal_error_if_fail (calobj != NULL && *calobj != '\0', InvalidArg);
@@ -2593,11 +1857,8 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
goto exit;
}
- /* pick all the tzids out of the component and resolve
- * them using the vtimezones in the current calendar */
- cbd.cbews = cbews;
- cbd.comp = icalcomp;
- icalcomponent_foreach_tzid (icalcomp, tzid_cb, &cbd);
+ if (!e_ews_connection_satisfies_server_version (cbews->priv->cnc, E_EWS_EXCHANGE_2010))
+ e_cal_backend_ews_pick_all_tzids_out (cbews, icalcomp);
comp = e_cal_component_new ();
e_cal_component_set_icalcomponent (comp, icalcomp);
@@ -2609,7 +1870,6 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
g_propagate_error (
&error, EDC_ERROR_EX (OtherError,
"Cannot determine EWS ItemId"));
- g_object_unref (comp);
goto exit;
}
@@ -2617,14 +1877,13 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
oldcomp = g_hash_table_lookup (priv->item_id_hash, itemid);
if (!oldcomp) {
g_propagate_error (&error, EDC_ERROR (ObjectNotFound));
- g_object_unref (comp);
PRIV_UNLOCK (priv);
goto exit;
}
PRIV_UNLOCK (priv);
- cbd.comp = e_cal_component_get_icalcomponent (oldcomp);
- icalcomponent_foreach_tzid (cbd.comp, tzid_cb, &cbd);
+ if (!e_ews_connection_satisfies_server_version (cbews->priv->cnc, E_EWS_EXCHANGE_2010))
+ e_cal_backend_ews_pick_all_tzids_out (cbews, e_cal_component_get_icalcomponent (oldcomp));
/*In case we have updated attachments we have to run update attachments
*before update items so attendees will receive mails with already updated attachments */
@@ -2681,16 +1940,15 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
EwsId *item_id = g_new0 (EwsId, 1);
item_id->id = itemid;
item_id->change_key = changekey;
- attach_data = g_new0 (EwsAttachmentsData, 1);
+ attach_data = g_new0 (EwsCalendarAsyncData, 1);
attach_data->cbews = g_object_ref (cbews);
attach_data->comp = g_object_ref (comp);
- attach_data->cb_type = 2;
- attach_data->oldcomp = g_object_ref (oldcomp);
+ attach_data->cb_type = E_EWS_ATTACHMENT_TYPE_UPDATE;
+ attach_data->extra_comp = g_object_ref (oldcomp);
attach_data->cal = g_object_ref (cal);
attach_data->context = 0;
- attach_data->itemid = itemid;
- attach_data->changekey = changekey;
+ attach_data->item_id = itemid;
e_cal_component_get_uid (oldcomp, &old_uid);
if (old_uid)
@@ -2734,17 +1992,25 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
g_free (item_id);
} else {
+ EwsCalendarConvertData convert_data;
const gchar *send_meeting_invitations;
const gchar *send_or_save;
- modify_data = g_new0 (EwsModifyData, 1);
+ modify_data = g_new0 (EwsCalendarAsyncData, 1);
modify_data->cbews = g_object_ref (cbews);
modify_data->comp = g_object_ref (comp);
- modify_data->oldcomp = g_object_ref (oldcomp);
+ modify_data->extra_comp = g_object_ref (oldcomp);
modify_data->cal = g_object_ref (cal);
modify_data->context = context;
- modify_data->itemid = itemid;
- modify_data->changekey = changekey;
+ modify_data->item_id = itemid;
+
+ convert_data.connection = cbews->priv->cnc;
+ convert_data.user_email = cbews->priv->user_email;
+ convert_data.comp = comp;
+ convert_data.old_comp = oldcomp;
+ convert_data.item_id = itemid;
+ convert_data.change_key = changekey;
+ convert_data.default_zone = cbews->priv->default_zone;
if (e_cal_component_has_attendees (comp)) {
send_meeting_invitations = "SendToAllAndSaveCopy";
@@ -2761,8 +2027,8 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
send_or_save,
send_meeting_invitations,
priv->folder_id,
- convert_component_to_updatexml,
- modify_data,
+ e_cal_backend_ews_convert_component_to_updatexml,
+ &convert_data,
cancellable,
ews_cal_modify_object_cb,
modify_data);
@@ -2770,6 +2036,9 @@ e_cal_backend_ews_modify_object (ECalBackend *backend,
return;
exit:
+ if (comp != NULL)
+ g_object_unref (comp);
+
convert_error_to_edc_error (&error);
if (context)
e_data_cal_respond_modify_objects (cal, context, error, NULL, NULL);
@@ -2779,12 +2048,6 @@ exit:
}
}
-typedef struct {
- const gchar *response_type;
- const gchar *item_id;
- const gchar *change_key;
-} EwsAcceptData;
-
static void
e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
icalcomponent *subcomp,
@@ -2792,12 +2055,12 @@ e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
GCancellable *cancellable,
GError **error)
{
- EwsConvertData *convert_data;
+ EwsCalendarConvertData convert_data;
EwsFolderId *fid;
- convert_data = g_new0 (EwsConvertData, 1);
- convert_data->cbews = g_object_ref (cbews);
- convert_data->icalcomp = subcomp;
+ convert_data.connection = cbews->priv->cnc;
+ convert_data.icalcomp = subcomp;
+ convert_data.default_zone = cbews->priv->default_zone;
fid = e_ews_folder_id_new (cbews->priv->folder_id, NULL, FALSE);
@@ -2807,8 +2070,8 @@ e_ews_receive_objects_no_exchange_mail (ECalBackendEws *cbews,
"SaveOnly",
"SendToNone",
fid,
- convert_calcomp_to_xml,
- convert_data,
+ e_cal_backend_ews_convert_calcomp_to_xml,
+ &convert_data,
ids,
cancellable,
error);
@@ -2852,49 +2115,155 @@ e_ews_get_current_user_meeting_reponse (icalcomponent *icalcomp,
}
static void
-prepare_accept_item_request (ESoapMessage *msg,
- gpointer user_data)
+ews_cal_do_method_request_publish_reply (ECalBackendEws *cbews,
+ ECalComponent *comp,
+ icalcomponent *subcomp,
+ const gchar *response_type,
+ GCancellable *cancellable,
+ GError **error)
{
- EwsAcceptData *data = user_data;
- const gchar *response_type = data->response_type;
-
- /* FORMAT OF A SAMPLE SOAP MESSAGE:
http://msdn.microsoft.com/en-us/library/aa566464%28v=exchg.140%29.aspx
- * Accept and Decline meeting have same method code (10032)
- * The real status is reflected at Attendee property PARTSTAT
- * need to find current user as attendee and make a decision what to do.
- * Prepare AcceptItem node in the SOAP message */
-
- if (response_type && !g_ascii_strcasecmp (response_type, "ACCEPTED"))
- e_soap_message_start_element (msg, "AcceptItem", NULL, NULL);
- else if (response_type && !g_ascii_strcasecmp (response_type, "DECLINED"))
- e_soap_message_start_element (msg, "DeclineItem", NULL, NULL);
- else
- e_soap_message_start_element (msg, "TentativelyAcceptItem", NULL, NULL);
+ GError *local_error = NULL;
+ gchar *item_id = NULL;
+ gchar *change_key = NULL;
+ gchar *mail_id = NULL;
+ gint pass = 0;
- e_soap_message_start_element (msg, "ReferenceItemId", NULL, NULL);
- e_soap_message_add_attribute (msg, "Id", data->item_id, NULL, NULL);
- e_soap_message_add_attribute (msg, "ChangeKey", data->change_key, NULL, NULL);
- e_soap_message_end_element (msg); // "ReferenceItemId"
+ ews_cal_component_get_calendar_item_accept_id (comp, &item_id, &change_key, &mail_id);
- /* end of "AcceptItem" */
- e_soap_message_end_element (msg);
-}
+ while (pass < 2) {
+ GSList *ids = NULL;
-static void
-prepare_set_free_busy_status (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsAcceptData *data = user_data;
+ /*in case we do not have item id we will create item with mime content only*/
+ if (item_id == NULL) {
+ e_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids, cancellable,
&local_error);
+ } else {
+ EwsCalendarConvertData convert_data;
- e_ews_message_start_item_change (msg, E_EWS_ITEMCHANGE_TYPE_ITEM, data->item_id, data->change_key, 0);
+ convert_data.response_type = (gchar *) response_type;
+ convert_data.item_id = item_id;
+ convert_data.change_key = change_key;
- e_ews_message_start_set_item_field (msg, "LegacyFreeBusyStatus", "calendar", "CalendarItem");
+ e_ews_connection_create_items_sync (
+ cbews->priv->cnc,
+ EWS_PRIORITY_MEDIUM,
+ "SendAndSaveCopy",
+ NULL,
+ NULL,
+ e_cal_backend_ews_prepare_accept_item_request,
+ &convert_data,
+ &ids,
+ cancellable,
+ &local_error);
+ }
+
+ if (pass == 0 && mail_id != NULL && item_id != NULL &&
+ g_error_matches (local_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_ITEMNOTFOUND)) {
+ /*
+ * maybe the associated accept calendar item changed
+ * on the server, thus retry with updated values
+ */
+ GSList *ids = NULL, *my_ids = NULL;
+
+ g_clear_error (&local_error);
+
+ my_ids = g_slist_append (my_ids, mail_id);
+
+ if (e_ews_connection_get_items_sync (
+ cbews->priv->cnc,
+ EWS_PRIORITY_MEDIUM,
+ my_ids,
+ "AllProperties",
+ NULL,
+ FALSE,
+ NULL,
+ E_EWS_BODY_TYPE_ANY,
+ &ids,
+ NULL,
+ NULL,
+ cancellable,
+ &local_error) &&
+ ids != NULL &&
+ ids->data != NULL) {
+ EEwsItem *item = ids->data;
+ const EwsId *id = e_ews_item_get_id (item);
+
+ if (id != NULL && g_strcmp0 (id->id, mail_id) == 0) {
+ const EwsId *cal_item_accepted_id;
+
+ cal_item_accepted_id = e_ews_item_get_calendar_item_accept_id (item);
+ if (cal_item_accepted_id != NULL) {
+ g_clear_error (&local_error);
+ pass++;
+
+ g_free (item_id);
+ g_free (change_key);
+
+ item_id = g_strdup (cal_item_accepted_id->id);
+ change_key = g_strdup (cal_item_accepted_id->change_key);
+ }
+ }
+ }
+
+ g_slist_free (my_ids);
+ g_slist_free_full (ids, g_object_unref);
+
+ if (pass == 0)
+ break;
+ } else {
+ break;
+ }
+ }
+
+ if (error == NULL) {
+ icalproperty *transp;
+
+ transp = icalcomponent_get_first_property (subcomp, ICAL_TRANSP_PROPERTY);
+
+ if (g_strcmp0 (icalproperty_get_value_as_string (transp), "TRANSPARENT") == 0 &&
+ g_strcmp0 (response_type, "ACCEPTED") == 0) {
+ EwsCalendarConvertData convert_data;
+ GSList *l, *ids = NULL;
- e_ews_message_write_string_parameter (msg, "LegacyFreeBusyStatus", NULL, "Free");
+ /*
+ * user can accept meeting but mark it as free in it's calendar
+ * the following code is updating the exchange meeting status to free
+ */
+ for (l = ids; l != NULL; l = g_slist_next (l)) {
+ EEwsItem *item = l->data;
- e_ews_message_end_set_item_field (msg);
+ if (item != NULL) {
+ const EwsId *id = e_ews_item_get_id (item);
- e_ews_message_end_item_change (msg);
+ convert_data.item_id = id->id;
+ convert_data.change_key = id->change_key;
+ break;
+ }
+ }
+
+ e_ews_connection_update_items_sync (
+ cbews->priv->cnc,
+ EWS_PRIORITY_MEDIUM,
+ "AlwaysOverwrite",
+ NULL,
+ "SendToNone",
+ NULL,
+ e_cal_backend_ews_prepare_set_free_busy_status,
+ &convert_data,
+ &ids,
+ cancellable,
+ &local_error);
+ }
+ }
+
+ if (error != NULL)
+ g_propagate_error (error, local_error);
+
+ g_free (item_id);
+ g_free (change_key);
+ g_free (mail_id);
+
+ /*We have to run sync before any other operations */
+ ews_start_sync (cbews);
}
static void
@@ -2910,7 +2279,6 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
icalcomponent *icalcomp, *subcomp;
GError *error = NULL;
icalproperty_method method;
- EwsAcceptData *accept_data;
cbews = E_CAL_BACKEND_EWS (backend);
priv = cbews->priv;
@@ -2947,115 +2315,26 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
while (subcomp) {
ECalComponent *comp = e_cal_component_new ();
const gchar *response_type;
- gchar *item_id = NULL, *change_key = NULL, *mail_id = NULL;
- GSList *ids = NULL, *l;
- icalproperty *transp, *summary;
- gchar **split_subject;
- gint pass = 0;
/* duplicate the ical component */
e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp));
/*getting a data for meeting request response*/
- response_type = e_ews_get_current_user_meeting_reponse (e_cal_component_get_icalcomponent
(comp), priv->user_email);
- ews_cal_component_get_calendar_item_accept_id (comp, &item_id, &change_key, &mail_id);
+ response_type = e_ews_get_current_user_meeting_reponse (
+ e_cal_component_get_icalcomponent (comp),
+ priv->user_email);
switch (method) {
case ICAL_METHOD_REQUEST:
case ICAL_METHOD_PUBLISH:
case ICAL_METHOD_REPLY:
- accept_data = g_new0 (EwsAcceptData, 1);
- accept_data->response_type = response_type;
- accept_data->item_id = item_id;
- accept_data->change_key = change_key;
-
- while (pass < 2) {
- /*in case we do not have item id we will create item with mime
content only*/
- if (item_id == NULL)
- e_ews_receive_objects_no_exchange_mail (cbews, subcomp, &ids,
cancellable, &error);
- else
- e_ews_connection_create_items_sync (
- priv->cnc, EWS_PRIORITY_MEDIUM,
- "SendAndSaveCopy",
- NULL, NULL,
- prepare_accept_item_request,
- accept_data,
- &ids, cancellable, &error);
- if (pass == 0 && mail_id && item_id &&
- g_error_matches (error, EWS_CONNECTION_ERROR,
EWS_CONNECTION_ERROR_ITEMNOTFOUND)) {
- /* maybe the associated accept calendar item changed
- on the server, thus retry with updated values */
- GSList *my_ids;
-
- my_ids = g_slist_append (NULL, mail_id);
- ids = NULL;
- if (e_ews_connection_get_items_sync (priv->cnc,
EWS_PRIORITY_MEDIUM, my_ids,
- "AllProperties", NULL, FALSE, NULL,
E_EWS_BODY_TYPE_ANY, &ids, NULL, NULL,
- cancellable, NULL)
- && ids && ids->data) {
- EEwsItem *item = ids->data;
- if (e_ews_item_get_id (item) &&
- g_strcmp0 (e_ews_item_get_id (item)->id, mail_id)
== 0) {
- const EwsId *calendar_item_accept_id =
e_ews_item_get_calendar_item_accept_id (item);
-
- if (calendar_item_accept_id) {
- g_clear_error (&error);
- pass++;
-
- g_free (item_id);
- g_free (change_key);
- item_id = g_strdup
(calendar_item_accept_id->id);
- change_key = g_strdup
(calendar_item_accept_id->change_key);
-
- accept_data->item_id = item_id;
- accept_data->change_key = change_key;
- }
- }
- }
-
- g_slist_free (my_ids);
- g_slist_free_full (ids, g_object_unref);
- ids = NULL;
-
- if (pass == 0)
- break;
- } else {
- break;
- }
- }
- if (!error) {
- transp = icalcomponent_get_first_property (subcomp,
ICAL_TRANSP_PROPERTY);
- if (!g_strcmp0 (icalproperty_get_value_as_string (transp),
"TRANSPARENT") &&
- !g_strcmp0 (response_type, "ACCEPTED")) {
- /*user can accept meeting but mark it as free in it's calendar
- the following code is updating the exchange meeting status
to free */
- for (l = ids; l != NULL; l = g_slist_next (l)) {
- EEwsItem *item = (EEwsItem *) l->data;
- if (item) {
- accept_data->item_id = e_ews_item_get_id
(item)->id;
- accept_data->change_key = e_ews_item_get_id
(item)->change_key;
- break;
- }
- }
- e_ews_connection_update_items_sync (
- priv->cnc,
- EWS_PRIORITY_MEDIUM,
- "AlwaysOverwrite",
- NULL, "SendToNone",
- NULL,
- prepare_set_free_busy_status,
- accept_data,
- &ids,
- cancellable,
- &error);
- }
- }
- g_free (item_id);
- g_free (change_key);
- g_free (mail_id);
- g_free (accept_data);
- /*We have to run sync before any other operations */
- ews_start_sync (cbews);
+ ews_cal_do_method_request_publish_reply (
+ cbews,
+ comp,
+ subcomp,
+ response_type,
+ cancellable,
+ &error);
break;
case ICAL_METHOD_CANCEL: {
const gchar *uid = NULL;
@@ -3071,13 +2350,21 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
break;
}
case ICAL_METHOD_COUNTER:
- /*this is a new time proposal mail from one of the attendees
+ /*
+ * this is a new time proposal mail from one of the attendees
* if we decline the proposal, nothing have to be done
- * if we accept it we will call to modify_object */
- if (!g_strcmp0 (response_type, "ACCEPTED")) {
- /*we have to edit the meeting subject to remove exchange header*/
+ * if we accept it we will call to modify_object
+ */
+ if (g_strcmp0 (response_type, "ACCEPTED") == 0) {
+ gchar **split_subject;
+ icalproperty *summary;
+
+ /*
+ * we have to edit the meeting subject to remove exchange header
+ */
summary = icalcomponent_get_first_property (subcomp,
ICAL_SUMMARY_PROPERTY);
- split_subject = g_strsplit (icalproperty_get_value_as_string
(summary), ":", -1);
+ split_subject =
+ g_strsplit (icalproperty_get_value_as_string (summary), ":",
-1);
icalproperty_set_value_from_string (summary, split_subject[1] , "NO");
g_strfreev (split_subject);
@@ -3087,6 +2374,7 @@ e_cal_backend_ews_receive_objects (ECalBackend *backend,
default:
break;
}
+
g_object_unref (comp);
subcomp = icalcomponent_get_next_component (icalcomp, kind);
}
@@ -3120,34 +2408,6 @@ e_cal_get_meeting_cancellation_comment (ECalComponent *comp)
return NULL;
}
-static icaltimezone *
-e_cal_get_timezone_from_ical_component (ECalBackend *backend,
- icalcomponent *comp)
-{
- ETimezoneCache *timezone_cache;
- icalproperty *prop;
- icalparameter *param;
-
- timezone_cache = E_TIMEZONE_CACHE (backend);
-
- prop = icalcomponent_get_first_property (
- comp, ICAL_DTSTART_PROPERTY);
- param = icalproperty_get_first_parameter (
- prop, ICAL_TZID_PARAMETER);
-
- if (param != NULL) {
- const gchar *tzid;
-
- tzid = icalparameter_get_tzid (param);
-
- return e_timezone_cache_get_timezone (timezone_cache, tzid);
- }
-
- g_warning ("EEE Cant figure the relevant timezone of the component\n");
-
- return NULL;
-}
-
static void
ewscal_send_cancellation_email (ECalBackend *backend,
EEwsConnection *cnc,
@@ -3178,7 +2438,8 @@ ewscal_send_cancellation_email (ECalBackend *backend,
prop = icalcomponent_get_first_property (vevent, ICAL_METHOD_PROPERTY);
if (prop != NULL) icalcomponent_remove_property (vevent, prop);
dt = icalcomponent_get_dtstart (vevent);
- icaltz = (icaltimezone *)(dt.zone ? dt.zone : e_cal_get_timezone_from_ical_component (backend,
vevent));
+ icaltz = (icaltimezone *)
+ (dt.zone ? dt.zone : e_cal_backend_ews_get_timezone_from_ical_component (backend, vevent));
vtz = icaltimezone_get_component (icaltz);
icalcomponent_add_component (vcal, icalcomponent_new_clone (vtz));
icalcomponent_add_component (vcal, vevent);
@@ -3609,9 +2870,17 @@ add_item_to_cache (ECalBackendEws *cbews,
zone = NULL;
tzid = e_ews_item_get_tzid (item);
- if (tzid != NULL)
+
+ if (tzid != NULL) {
+ const gchar *ical_location;
+
+ ical_location = e_cal_backend_ews_tz_util_get_ical_equivalent (tzid);
+
zone = e_timezone_cache_get_timezone (
- timezone_cache, tzid);
+ timezone_cache,
+ ical_location != NULL ? ical_location : tzid);
+ }
+
if (zone == NULL)
zone = icaltimezone_get_builtin_timezone (tzid);
@@ -3894,16 +3163,8 @@ ews_cal_sync_get_items_sync (ECalBackendEws *cbews,
ret = ews_cal_sync_get_items_sync (
cbews, modified_occurrences,
"IdOnly",
- "item:Attachments"
- " item:HasAttachments"
- " item:MimeContent"
- " item:Categories"
- " calendar:TimeZone"
- " calendar:UID"
- " calendar:Resources"
- " calendar:ModifiedOccurrences"
- " calendar:RequiredAttendees"
- " calendar:OptionalAttendees");
+ e_ews_connection_satisfies_server_version (priv->cnc, E_EWS_EXCHANGE_2010) ?
+ GET_ITEMS_SYNC_PROPERTIES_2010 : GET_ITEMS_SYNC_PROPERTIES_2007);
if (!ret)
goto exit;
@@ -3982,16 +3243,8 @@ cal_backend_ews_process_folder_items (ECalBackendEws *cbews,
cbews,
cal_item_ids,
"IdOnly",
- "item:Attachments"
- " item:Categories"
- " item:HasAttachments"
- " item:MimeContent"
- " calendar:TimeZone"
- " calendar:UID"
- " calendar:Resources"
- " calendar:ModifiedOccurrences"
- " calendar:RequiredAttendees"
- " calendar:OptionalAttendees");
+ e_ews_connection_satisfies_server_version (priv->cnc, E_EWS_EXCHANGE_2010) ?
+ GET_ITEMS_SYNC_PROPERTIES_2010 : GET_ITEMS_SYNC_PROPERTIES_2007);
}
if (task_memo_item_ids) {
@@ -4279,65 +3532,13 @@ exit:
e_data_cal_respond_refresh (cal, context, error);
}
-typedef struct {
- ECalBackendEws *cbews;
- EDataCal *cal;
- guint32 context;
- GSList *users;
- time_t start;
- time_t end;
-} EwsFreeBusyData;
-
-static void
-prepare_free_busy_request (ESoapMessage *msg,
- gpointer user_data)
-{
- EwsFreeBusyData *free_busy_data = user_data;
- GSList *addr;
- icaltimetype t_start, t_end;
- icaltimezone *utc_zone = icaltimezone_get_utc_timezone ();
-
- ewscal_set_availability_timezone (msg, utc_zone);
-
- e_soap_message_start_element (msg, "MailboxDataArray", "messages", NULL);
-
- for (addr = free_busy_data->users; addr; addr = addr->next) {
- e_soap_message_start_element (msg, "MailboxData", NULL, NULL);
-
- e_soap_message_start_element (msg, "Email", NULL, NULL);
- e_ews_message_write_string_parameter (msg, "Address", NULL, addr->data);
- e_soap_message_end_element (msg); /* "Email" */
-
- e_ews_message_write_string_parameter (msg, "AttendeeType", NULL, "Required");
- e_ews_message_write_string_parameter (msg, "ExcludeConflicts", NULL, "false");
-
- e_soap_message_end_element (msg); /* "MailboxData" */
- }
-
- e_soap_message_end_element (msg); /* "MailboxDataArray" */
-
- e_soap_message_start_element (msg, "FreeBusyViewOptions", NULL, NULL);
-
- e_soap_message_start_element (msg, "TimeWindow", NULL, NULL);
- t_start = icaltime_from_timet_with_zone (free_busy_data->start, 0, utc_zone);
- t_end = icaltime_from_timet_with_zone (free_busy_data->end, 0, utc_zone);
- ewscal_set_time (msg, "StartTime", &t_start, FALSE);
- ewscal_set_time (msg, "EndTime", &t_end, FALSE);
- e_soap_message_end_element (msg); /* "TimeWindow" */
-
- e_ews_message_write_string_parameter (msg, "MergedFreeBusyIntervalInMinutes", NULL, "60");
- e_ews_message_write_string_parameter (msg, "RequestedView", NULL, "DetailedMerged");
-
- e_soap_message_end_element (msg); /* "FreeBusyViewOptions" */
-}
-
static void
ews_cal_get_free_busy_cb (GObject *obj,
GAsyncResult *res,
gpointer user_data)
{
EEwsConnection *cnc = (EEwsConnection *) obj;
- EwsFreeBusyData *free_busy_data = user_data;
+ EwsCalendarAsyncData *free_busy_data = user_data;
GSList *free_busy_sl = NULL, *i;
GSList *free_busy = NULL, *j;
GError *error = NULL;
@@ -4360,12 +3561,8 @@ done:
convert_error_to_edc_error (&error);
e_data_cal_respond_get_free_busy (free_busy_data->cal, free_busy_data->context, error);
- /* FIXME free free_busy_sl ? */
g_slist_free_full (free_busy, g_free);
- g_slist_free_full (free_busy_data->users, g_free);
- g_object_unref (free_busy_data->cal);
- g_object_unref (free_busy_data->cbews);
- g_free (free_busy_data);
+ e_cal_backend_ews_async_data_free (free_busy_data);
}
static void
@@ -4380,7 +3577,8 @@ e_cal_backend_ews_get_free_busy (ECalBackend *backend,
ECalBackendEws *cbews = E_CAL_BACKEND_EWS (backend);
ECalBackendEwsPrivate *priv = cbews->priv;
GError *error = NULL;
- EwsFreeBusyData *free_busy_data;
+ EwsCalendarAsyncData *free_busy_data;
+ EwsCalendarConvertData convert_data;
GSList *users_copy = NULL;
/* make sure we're not offline */
@@ -4404,19 +3602,21 @@ e_cal_backend_ews_get_free_busy (ECalBackend *backend,
for (; users; users = users->next)
users_copy = g_slist_append (users_copy, g_strdup (users->data));
- free_busy_data = g_new0 (EwsFreeBusyData, 1);
+ free_busy_data = g_new0 (EwsCalendarAsyncData, 1);
free_busy_data->cbews = g_object_ref (cbews);
free_busy_data->cal = g_object_ref (cal);
free_busy_data->context = context;
free_busy_data->users = users_copy;
- free_busy_data->start = start;
- free_busy_data->end = end;
+
+ convert_data.users = users_copy;
+ convert_data.start = start;
+ convert_data.end = end;
e_ews_connection_get_free_busy (
priv->cnc,
EWS_PRIORITY_MEDIUM,
- prepare_free_busy_request,
- free_busy_data,
+ e_cal_backend_ews_prepare_free_busy_request,
+ &convert_data,
cancellable,
ews_cal_get_free_busy_cb,
free_busy_data);
@@ -4675,6 +3875,9 @@ e_cal_backend_ews_finalize (GObject *object)
g_free (priv);
cbews->priv = NULL;
+ e_cal_backend_ews_unref_tz_ical_to_msdn ();
+ e_cal_backend_ews_unref_tz_msdn_to_ical ();
+
G_OBJECT_CLASS (e_cal_backend_ews_parent_class)->finalize (object);
}
@@ -4792,5 +3995,8 @@ e_cal_backend_ews_init (ECalBackendEws *cbews)
g_signal_connect (
cbews, "notify::online",
G_CALLBACK (e_cal_backend_ews_notify_online_cb), NULL);
+
+ e_cal_backend_ews_populate_tz_ical_to_msdn ();
+ e_cal_backend_ews_populate_tz_msdn_to_ical ();
}
diff --git a/src/calendar/e-cal-backend-ews.h b/src/calendar/e-cal-backend-ews.h
index 0959405..48480f3 100644
--- a/src/calendar/e-cal-backend-ews.h
+++ b/src/calendar/e-cal-backend-ews.h
@@ -51,6 +51,15 @@ struct _ECalBackendEwsClass {
GType e_cal_backend_ews_get_type (void);
+const EEwsConnection *
+ e_cal_backend_ews_get_connection (ECalBackendEws *cbews);
+
+const icaltimezone *
+ e_cal_backend_ews_get_default_zone (ECalBackendEws *cbews);
+
+const gchar *
+ e_cal_backend_ews_get_user_email (ECalBackendEws *cbews);
+
G_END_DECLS
#endif
diff --git a/src/server/e-ews-connection.c b/src/server/e-ews-connection.c
index d549714..216145b 100644
--- a/src/server/e-ews-connection.c
+++ b/src/server/e-ews-connection.c
@@ -131,6 +131,7 @@ struct _EwsAsyncData {
GSList *items_created;
GSList *items_updated;
GSList *items_deleted;
+ GSList *tzds; /* EEwsCalendarTimeZoneDefinition */
gint total_items;
const gchar *directory;
@@ -204,6 +205,158 @@ e_ews_notification_event_free (EEwsNotificationEvent *event)
}
}
+EEwsCalendarTo *
+e_ews_calendar_to_new (void)
+{
+ return g_new0 (EEwsCalendarTo, 1);
+}
+
+void
+e_ews_calendar_to_free (EEwsCalendarTo *to) {
+ if (to != NULL) {
+ g_free (to->kind);
+ g_free (to->value);
+ }
+}
+
+EEwsCalendarAbsoluteDateTransition *
+e_ews_calendar_absolute_date_transition_new (void)
+{
+ return g_new0 (EEwsCalendarAbsoluteDateTransition, 1);
+}
+
+void
+e_ews_calendar_absolute_date_transition_free (EEwsCalendarAbsoluteDateTransition *adt)
+{
+ if (adt != NULL) {
+ e_ews_calendar_to_free (adt->to);
+ g_free (adt->date_time);
+ g_free (adt);
+ }
+}
+
+EEwsCalendarRecurringDayTransition *
+e_ews_calendar_recurring_day_transition_new (void)
+{
+ return g_new0 (EEwsCalendarRecurringDayTransition, 1);
+}
+
+void
+e_ews_calendar_recurring_day_transition_free (EEwsCalendarRecurringDayTransition *rdayt)
+{
+ if (rdayt != NULL) {
+ e_ews_calendar_to_free (rdayt->to);
+ g_free (rdayt->time_offset);
+ g_free (rdayt->month);
+ g_free (rdayt->day_of_week);
+ g_free (rdayt->occurrence);
+ g_free (rdayt);
+ }
+}
+
+EEwsCalendarRecurringDateTransition *
+e_ews_calendar_recurring_date_transition_new (void)
+{
+ return g_new0 (EEwsCalendarRecurringDateTransition, 1);
+}
+
+void
+e_ews_calendar_recurring_date_transition_free (EEwsCalendarRecurringDateTransition *rdatet)
+{
+ if (rdatet != NULL) {
+ e_ews_calendar_to_free (rdatet->to);
+ g_free (rdatet->time_offset);
+ g_free (rdatet->month);
+ g_free (rdatet->day);
+ g_free (rdatet);
+ }
+}
+
+EEwsCalendarPeriod *
+e_ews_calendar_period_new (void)
+{
+ return g_new0 (EEwsCalendarPeriod, 1);
+}
+
+void
+e_ews_calendar_period_free (EEwsCalendarPeriod *period)
+{
+ if (period != NULL) {
+ g_free (period->bias);
+ g_free (period->name);
+ g_free (period->id);
+ g_free (period);
+ }
+}
+
+EEwsCalendarTransitionsGroup *
+e_ews_calendar_transitions_group_new (void)
+{
+ return g_new0 (EEwsCalendarTransitionsGroup, 1);
+}
+
+void
+e_ews_calendar_transitions_group_free (EEwsCalendarTransitionsGroup *tg)
+{
+ if (tg != NULL) {
+ g_free (tg->id);
+ e_ews_calendar_to_free (tg->transition);
+ g_slist_free_full (
+ tg->absolute_date_transitions,
+ (GDestroyNotify) e_ews_calendar_absolute_date_transition_free);
+ g_slist_free_full (
+ tg->recurring_day_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_day_transition_free);
+ g_slist_free_full (
+ tg->recurring_date_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_date_transition_free);
+ g_free (tg);
+ }
+}
+
+EEwsCalendarTransitions *
+e_ews_calendar_transitions_new (void)
+{
+ return g_new0 (EEwsCalendarTransitions, 1);
+}
+
+void
+e_ews_calendar_transitions_free (EEwsCalendarTransitions *transitions)
+{
+ if (transitions != NULL) {
+ e_ews_calendar_to_free (transitions->transition);
+ g_slist_free_full (
+ transitions->absolute_date_transitions,
+ (GDestroyNotify) e_ews_calendar_absolute_date_transition_free);
+ g_slist_free_full (
+ transitions->recurring_day_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_day_transition_free);
+ g_slist_free_full (
+ transitions->recurring_date_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_date_transition_free);
+ g_free (transitions);
+ }
+}
+
+EEwsCalendarTimeZoneDefinition *
+e_ews_calendar_time_zone_definition_new (void)
+{
+ return g_new0 (EEwsCalendarTimeZoneDefinition, 1);
+}
+
+void
+e_ews_calendar_time_zone_definition_free (EEwsCalendarTimeZoneDefinition *tzd)
+{
+ if (tzd != NULL) {
+ g_free (tzd->name);
+ g_free (tzd->id);
+ g_slist_free_full (tzd->periods, (GDestroyNotify) e_ews_calendar_period_free);
+ g_slist_free_full (tzd->transitions_groups, (GDestroyNotify)
e_ews_calendar_transitions_group_free);
+ e_ews_calendar_transitions_free (tzd->transitions);
+ g_free (tzd);
+ }
+}
+
static EwsNode *
ews_node_new ()
{
@@ -9246,3 +9399,647 @@ e_ews_connection_disable_notifications_sync (EEwsConnection *cnc,
exit:
NOTIFICATION_UNLOCK (cnc);
}
+
+static EEwsCalendarTo *
+ews_get_to (ESoapParameter *node)
+{
+ EEwsCalendarTo *to = NULL;
+ ESoapParameter *param;
+ gchar *kind = NULL;
+ gchar *value = NULL;
+ gboolean success = FALSE;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "To");
+ if (param == NULL)
+ goto exit;
+
+ kind = e_soap_parameter_get_property (param, "Kind");
+ if (kind == NULL)
+ goto exit;
+
+ value = e_soap_parameter_get_string_value (param);
+ if (value == NULL)
+ goto exit;
+
+ success = TRUE;
+
+exit:
+ if (success) {
+ to = e_ews_calendar_to_new ();
+ to->kind = kind;
+ to->value = value;
+ } else {
+ g_free (kind);
+ g_free (value);
+ }
+
+ return to;
+}
+
+static EEwsCalendarPeriod *
+ews_get_period (ESoapParameter *node)
+{
+ EEwsCalendarPeriod *period = NULL;
+ gchar *bias = NULL;
+ gchar *name = NULL;
+ gchar *id = NULL;
+
+ bias = e_soap_parameter_get_property (node, "Bias");
+ name = e_soap_parameter_get_property (node, "Name");
+ id = e_soap_parameter_get_property (node, "Id");
+
+ if (bias == NULL || name == NULL || id == NULL) {
+ g_free (bias);
+ g_free (name);
+ g_free (id);
+
+ return NULL;
+ }
+
+ period = e_ews_calendar_period_new ();
+ period->bias = bias;
+ period->name = name;
+ period->id = id;
+
+ return period;
+}
+
+static GSList *
+ews_get_periods_list (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ GSList *periods = NULL;
+
+ for (param = e_soap_parameter_get_first_child_by_name (node, "Period");
+ param != NULL;
+ param = e_soap_parameter_get_next_child_by_name (param, "Period")) {
+ EEwsCalendarPeriod *period;
+
+ period = ews_get_period (param);
+ if (period != NULL) {
+ periods = g_slist_prepend (periods, period);
+ } else {
+ g_slist_free_full (periods, (GDestroyNotify) e_ews_calendar_period_free);
+ return NULL;
+ }
+ }
+
+ periods = g_slist_reverse (periods);
+ return periods;
+}
+
+static EEwsCalendarAbsoluteDateTransition *
+ews_get_absolute_date_transition (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ EEwsCalendarAbsoluteDateTransition *absolute_date_transition = NULL;
+ EEwsCalendarTo *to = NULL;
+ gchar *date_time = NULL;
+ gboolean success = FALSE;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "To");
+ if (param != NULL)
+ to = ews_get_to (param);
+
+ if (to == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "DateTime");
+ if (param != NULL)
+ date_time = e_soap_parameter_get_string_value (param);
+
+ if (date_time == NULL)
+ goto exit;
+
+ success = TRUE;
+
+exit:
+ if (success) {
+ absolute_date_transition = e_ews_calendar_absolute_date_transition_new ();
+ absolute_date_transition->to = to;
+ absolute_date_transition->date_time = date_time;
+ } else {
+ e_ews_calendar_to_free (to);
+ g_free (date_time);
+ }
+
+ return absolute_date_transition;
+}
+
+static EEwsCalendarRecurringDateTransition *
+ews_get_recurring_date_transition (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ EEwsCalendarRecurringDateTransition *recurring_date_transition = NULL;
+ EEwsCalendarTo *to = NULL;
+ gchar *time_offset = NULL;
+ gchar *month = NULL;
+ gchar *day = NULL;
+ gboolean success = FALSE;
+
+ to = ews_get_to (node);
+ if (to == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "TimeOffset");
+ if (param != NULL)
+ time_offset = e_soap_parameter_get_string_value (param);
+
+ if (time_offset == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Month");
+ if (param != NULL)
+ month = e_soap_parameter_get_string_value (param);
+
+ if (month == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Day");
+ if (param != NULL)
+ day = e_soap_parameter_get_string_value (param);
+
+ if (day == NULL)
+ goto exit;
+
+ success = TRUE;
+
+exit:
+ if (success) {
+ recurring_date_transition = e_ews_calendar_recurring_date_transition_new ();
+ recurring_date_transition->to = to;
+ recurring_date_transition->time_offset = time_offset;
+ recurring_date_transition->month = month;
+ recurring_date_transition->day = day;
+ } else {
+ e_ews_calendar_to_free (to);
+ g_free (time_offset);
+ g_free (month);
+ g_free (day);
+ }
+
+ return recurring_date_transition;
+}
+
+static EEwsCalendarRecurringDayTransition *
+ews_get_recurring_day_transition (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ EEwsCalendarRecurringDayTransition *recurring_day_transition = NULL;
+ EEwsCalendarTo *to = NULL;
+ gchar *time_offset = NULL;
+ gchar *month = NULL;
+ gchar *day_of_week = NULL;
+ gchar *occurrence = NULL;
+ gboolean success = FALSE;
+
+ to = ews_get_to (node);
+ if (to == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "TimeOffset");
+ if (param != NULL)
+ time_offset = e_soap_parameter_get_string_value (param);
+
+ if (time_offset == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Month");
+ if (param != NULL)
+ month = e_soap_parameter_get_string_value (param);
+
+ if (month == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "DayOfWeek");
+ if (param != NULL)
+ day_of_week = e_soap_parameter_get_string_value (param);
+
+ if (day_of_week == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Occurrence");
+ if (param != NULL)
+ occurrence = e_soap_parameter_get_string_value (param);
+
+ if (occurrence == NULL)
+ goto exit;
+
+ success = TRUE;
+
+exit:
+ if (success) {
+ recurring_day_transition = e_ews_calendar_recurring_day_transition_new ();
+ recurring_day_transition->to = to;
+ recurring_day_transition->time_offset = time_offset;
+ recurring_day_transition->month = month;
+ recurring_day_transition->day_of_week = day_of_week;
+ recurring_day_transition->occurrence = occurrence;
+ } else {
+ e_ews_calendar_to_free (to);
+ g_free (time_offset);
+ g_free (month);
+ g_free (day_of_week);
+ g_free (occurrence);
+ }
+
+ return recurring_day_transition;
+}
+
+static GSList *
+ews_get_absolute_date_transitions_list (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ GSList *absolute_date_transitions = NULL;
+
+ for (param = e_soap_parameter_get_first_child_by_name (node, "AbsoluteDateTransition");
+ param != NULL;
+ param = e_soap_parameter_get_next_child_by_name (param, "AbsoluteDateTransition")) {
+ EEwsCalendarAbsoluteDateTransition *absolute_date_transition;
+
+ absolute_date_transition = ews_get_absolute_date_transition (param);
+ if (absolute_date_transition != NULL) {
+ absolute_date_transitions =
+ g_slist_prepend (absolute_date_transitions, absolute_date_transition);
+ } else {
+ g_slist_free_full (
+ absolute_date_transitions,
+ (GDestroyNotify) e_ews_calendar_absolute_date_transition_free);
+ return NULL;
+ }
+ }
+
+ absolute_date_transitions = g_slist_reverse (absolute_date_transitions);
+ return absolute_date_transitions;
+}
+
+static GSList *
+ews_get_recurring_day_transitions_list (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ GSList *recurring_day_transitions = NULL;
+
+ for (param = e_soap_parameter_get_first_child_by_name (node, "RecurringDayTransition");
+ param != NULL;
+ param = e_soap_parameter_get_next_child_by_name (param, "RecurringDayTransition")) {
+ EEwsCalendarRecurringDayTransition *recurring_day_transition;
+
+ recurring_day_transition = ews_get_recurring_day_transition (param);
+ if (recurring_day_transition != NULL) {
+ recurring_day_transitions =
+ g_slist_prepend (recurring_day_transitions, recurring_day_transition);
+ } else {
+ g_slist_free_full (
+ recurring_day_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_day_transition_free);
+ return NULL;
+ }
+ }
+
+ recurring_day_transitions = g_slist_reverse (recurring_day_transitions);
+ return recurring_day_transitions;
+}
+
+static GSList *
+ews_get_recurring_date_transitions_list (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ GSList *recurring_date_transitions = NULL;
+
+ for (param = e_soap_parameter_get_first_child_by_name (node, "RecurringDateTransition");
+ param != NULL;
+ param = e_soap_parameter_get_next_child_by_name (param, "RecurringDateTransition")) {
+ EEwsCalendarRecurringDateTransition *recurring_date_transition;
+
+ recurring_date_transition = ews_get_recurring_date_transition (param);
+ if (recurring_date_transition != NULL) {
+ recurring_date_transitions =
+ g_slist_prepend (recurring_date_transitions, recurring_date_transition);
+ } else {
+ g_slist_free_full (
+ recurring_date_transitions,
+ (GDestroyNotify) e_ews_calendar_recurring_date_transition_free);
+ return NULL;
+ }
+ }
+
+ recurring_date_transitions = g_slist_reverse (recurring_date_transitions);
+ return recurring_date_transitions;
+}
+
+static EEwsCalendarTransitionsGroup *
+ews_get_transitions_group (ESoapParameter *node)
+{
+ EEwsCalendarTransitionsGroup *tg = NULL;
+ EEwsCalendarTo *transition = NULL;
+ ESoapParameter *param = NULL;
+ gchar *id = NULL;
+ GSList *absolute_date_transitions = NULL;
+ GSList *recurring_date_transitions = NULL;
+ GSList *recurring_day_transitions = NULL;
+
+ id = e_soap_parameter_get_property (node, "Id");
+ if (id == NULL)
+ return NULL;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Transition");
+ if (param != NULL)
+ transition = ews_get_to (param);
+
+ absolute_date_transitions = ews_get_absolute_date_transitions_list (node);
+ recurring_date_transitions = ews_get_recurring_date_transitions_list (node);
+ recurring_day_transitions = ews_get_recurring_day_transitions_list (node);
+
+ tg = e_ews_calendar_transitions_group_new ();
+ tg->id = id;
+ tg->transition = transition;
+ tg->absolute_date_transitions = absolute_date_transitions;
+ tg->recurring_date_transitions = recurring_date_transitions;
+ tg->recurring_day_transitions = recurring_day_transitions;
+
+ return tg;
+}
+
+static GSList *
+ews_get_transitions_groups_list (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ GSList *transitions_groups = NULL;
+
+ for (param = e_soap_parameter_get_first_child_by_name (node, "TransitionsGroup");
+ param != NULL;
+ param = e_soap_parameter_get_next_child_by_name (param, "TransitionsGroup")) {
+ EEwsCalendarTransitionsGroup *tg;
+
+ tg = ews_get_transitions_group (param);
+ if (tg != NULL) {
+ transitions_groups = g_slist_prepend (transitions_groups, tg);
+ } else {
+ g_slist_free_full (transitions_groups, (GDestroyNotify)
e_ews_calendar_transitions_group_free);
+ return NULL;
+ }
+ }
+
+ transitions_groups = g_slist_reverse (transitions_groups);
+ return transitions_groups;
+}
+
+static EEwsCalendarTransitions *
+ews_get_transitions (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ EEwsCalendarTransitions *transitions = NULL;
+ EEwsCalendarTo *transition = NULL;
+ GSList *absolute_date_transitions = NULL;
+ GSList *recurring_date_transitions = NULL;
+ GSList *recurring_day_transitions = NULL;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Transition");
+ if (param != NULL)
+ transition = ews_get_to (param);
+
+ if (transition == NULL)
+ return NULL;
+
+ absolute_date_transitions = ews_get_absolute_date_transitions_list (node);
+ recurring_day_transitions = ews_get_recurring_day_transitions_list (node);
+ recurring_date_transitions = ews_get_recurring_date_transitions_list (node);
+
+ transitions = e_ews_calendar_transitions_new ();
+ transitions->transition = transition;
+ transitions->absolute_date_transitions = absolute_date_transitions;
+ transitions->recurring_day_transitions = recurring_day_transitions;
+ transitions->recurring_date_transitions = recurring_date_transitions;
+
+ return transitions;
+}
+
+static EEwsCalendarTimeZoneDefinition *
+ews_get_time_zone_definition (ESoapParameter *node)
+{
+ ESoapParameter *param;
+ gchar *name = NULL;
+ gchar *id = NULL;
+ GSList *periods = NULL;
+ GSList *transitions_groups = NULL;
+ EEwsCalendarTransitions *transitions = NULL;
+ EEwsCalendarTimeZoneDefinition *tzd = NULL;
+ gboolean success = FALSE;
+
+ name = e_soap_parameter_get_property (node, "Name");
+ if (name == NULL)
+ goto exit;
+
+ id = e_soap_parameter_get_property (node, "Id");
+ if (id == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Periods");
+ if (param != NULL)
+ periods = ews_get_periods_list (param);
+ if (periods == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "TransitionsGroups");
+ if (param != NULL)
+ transitions_groups = ews_get_transitions_groups_list (param);
+ if (transitions_groups == NULL)
+ goto exit;
+
+ param = e_soap_parameter_get_first_child_by_name (node, "Transitions");
+ if (param != NULL)
+ transitions = ews_get_transitions (param);
+ if (transitions == NULL)
+ goto exit;
+
+ success = TRUE;
+
+exit:
+ if (success) {
+ tzd = e_ews_calendar_time_zone_definition_new ();
+ tzd->name = name;
+ tzd->id = id;
+ tzd->periods = periods;
+ tzd->transitions_groups = transitions_groups;
+ tzd->transitions = transitions;
+ } else {
+ g_free (name);
+ g_free (id);
+ g_slist_free_full (periods, (GDestroyNotify) e_ews_calendar_period_free);
+ g_slist_free_full (transitions_groups, (GDestroyNotify)
e_ews_calendar_transitions_group_free);
+ e_ews_calendar_transitions_free (transitions);
+ }
+
+ return tzd;
+}
+
+static void
+get_server_time_zones_response_cb (ESoapResponse *response,
+ GSimpleAsyncResult *simple)
+{
+ EwsAsyncData *async_data;
+ ESoapParameter *param;
+ ESoapParameter *subparam;
+ GError *error = NULL;
+
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ param = e_soap_response_get_first_parameter_by_name (
+ response, "ResponseMessages", &error);
+
+ /* Sanity check */
+ g_return_if_fail (
+ (param != NULL && error == NULL) ||
+ (param == NULL && error != NULL));
+
+ if (error != NULL) {
+ g_simple_async_result_take_error (simple, error);
+ return;
+ }
+
+ subparam = e_soap_parameter_get_first_child (param);
+
+ while (subparam != NULL) {
+ const gchar *name = (const gchar *) subparam->name;
+
+ if (!ews_get_response_status (subparam, &error)) {
+ g_simple_async_result_take_error (simple, error);
+ return;
+ }
+
+ if (E_EWS_CONNECTION_UTILS_CHECK_ELEMENT (name, "GetServerTimeZonesResponseMessage")) {
+ ESoapParameter *node, *node2;
+
+ node = e_soap_parameter_get_first_child_by_name (subparam, "TimeZoneDefinitions");
+ if (node != NULL) {
+ node2 = e_soap_parameter_get_first_child_by_name (node, "TimeZoneDefinition");
+ if (node2 != NULL) {
+ EEwsCalendarTimeZoneDefinition *tzd;
+
+ tzd = ews_get_time_zone_definition (node2);
+ if (tzd != NULL)
+ async_data->tzds = g_slist_prepend (async_data->tzds, tzd);
+ }
+ }
+ }
+
+ subparam = e_soap_parameter_get_next_child (subparam);
+ }
+
+ async_data->tzds = g_slist_reverse (async_data->tzds);
+}
+
+void
+e_ews_connection_get_server_time_zones (EEwsConnection *cnc,
+ gint pri,
+ GSList *msdn_locations,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ESoapMessage *msg;
+ GSimpleAsyncResult *simple;
+ EwsAsyncData *async_data;
+ GSList *l;
+
+ g_return_if_fail (cnc != NULL);
+ g_return_if_fail (cnc->priv != NULL);
+
+ simple = g_simple_async_result_new (
+ G_OBJECT (cnc), callback, user_data, e_ews_connection_get_server_time_zones);
+ async_data = g_new0 (EwsAsyncData, 1);
+ g_simple_async_result_set_op_res_gpointer (simple, async_data, (GDestroyNotify) async_data_free);
+
+ /*
+ * EWS server version earlier than 2010 doesn't have support to "GetServerTimeZones".
+ * So, if the API is called with an older Exchange's version, let's just fail silently.
+ */
+ if (!e_ews_connection_satisfies_server_version (cnc, E_EWS_EXCHANGE_2010_SP1)) {
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ msg = e_ews_message_new_with_header (
+ cnc->priv->uri,
+ cnc->priv->impersonate_user,
+ "GetServerTimeZones",
+ "ReturnFullTimeZoneData",
+ "true",
+ cnc->priv->version,
+ E_EWS_EXCHANGE_2010,
+ FALSE,
+ TRUE);
+
+ e_soap_message_start_element (msg, "Ids", "messages", NULL);
+ for (l = msdn_locations; l != NULL; l = l->next)
+ e_ews_message_write_string_parameter_with_attribute (msg, "Id", NULL, l->data, NULL, NULL);
+ e_soap_message_end_element (msg); /* Ids */
+
+ e_ews_message_write_footer (msg); /* Complete the footer and print the request */
+
+ e_ews_connection_queue_request (cnc, msg, get_server_time_zones_response_cb, pri, cancellable,
simple);
+
+ g_object_unref (simple);
+}
+
+gboolean
+e_ews_connection_get_server_time_zones_finish (EEwsConnection *cnc,
+ GAsyncResult *result,
+ GSList **tzds, /*EEwsCalendarTimeZoneDefinition */
+ GError **error)
+{
+ GSimpleAsyncResult *simple;
+ EwsAsyncData *async_data;
+
+ g_return_val_if_fail (cnc != NULL, FALSE);
+ g_return_val_if_fail (
+ g_simple_async_result_is_valid (result, G_OBJECT (cnc),
e_ews_connection_get_server_time_zones),
+ FALSE);
+
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ async_data = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ if (async_data->tzds == NULL)
+ return FALSE;
+
+ if (tzds != NULL)
+ *tzds = async_data->tzds;
+ else
+ g_slist_free_full (
+ async_data->tzds,
+ (GDestroyNotify) e_ews_calendar_time_zone_definition_free);
+
+ return TRUE;
+}
+
+gboolean
+e_ews_connection_get_server_time_zones_sync (EEwsConnection *cnc,
+ gint pri,
+ GSList *msdn_locations,
+ GSList **tzds, /* EEwsCalendarTimeZoneDefinition */
+ GCancellable *cancellable,
+ GError **error)
+{
+ EAsyncClosure *closure;
+ GAsyncResult *result;
+ gboolean success;
+
+ g_return_val_if_fail (cnc != NULL, FALSE);
+
+ closure = e_async_closure_new ();
+
+ e_ews_connection_get_server_time_zones (
+ cnc, pri, msdn_locations, cancellable, e_async_closure_callback, closure);
+
+ result = e_async_closure_wait (closure);
+
+ success = e_ews_connection_get_server_time_zones_finish (cnc, result, tzds, error);
+
+ e_async_closure_free (closure);
+
+ return success;
+}
diff --git a/src/server/e-ews-connection.h b/src/server/e-ews-connection.h
index e0a3067..7ac47e9 100644
--- a/src/server/e-ews-connection.h
+++ b/src/server/e-ews-connection.h
@@ -221,6 +221,162 @@ typedef struct {
gchar *old_folder_id;
} EEwsNotificationEvent;
+/*
+ * <To Kind=""/>
+ */
+typedef struct {
+ gchar *kind;
+ gchar *value;
+} EEwsCalendarTo;
+
+/*
+ * <AbsoluteDateTransition>
+ * <To/>
+ * <DateTime/>
+ * </AbsoluteDateTransition>
+ */
+typedef struct {
+ EEwsCalendarTo *to;
+ gchar *date_time;
+} EEwsCalendarAbsoluteDateTransition;
+
+/*
+ * <RecurringDayTransition>
+ * <To/>
+ * <TimeOffset/>
+ * <Month/>
+ * <DayOfWeek/>
+ * <Ocurrence/>
+ * </RecurringDayTransition>
+ */
+typedef struct {
+ EEwsCalendarTo *to;
+ gchar *time_offset;
+ gchar *month;
+ gchar *day_of_week;
+ gchar *occurrence;
+} EEwsCalendarRecurringDayTransition;
+
+/*
+ * <RecurringDateTransition>
+ * <To/>
+ * <TimeOffset/>
+ * <Month/>
+ * <Day/>
+ * </RecurringDateTransition>
+ */
+typedef struct {
+ EEwsCalendarTo *to;
+ gchar *time_offset;
+ gchar *month;
+ gchar *day;
+} EEwsCalendarRecurringDateTransition;
+
+/*
+ * <Period Bias="" Name="" Id=""/>
+ */
+typedef struct {
+ gchar *bias;
+ gchar *name;
+ gchar *id;
+} EEwsCalendarPeriod;
+
+/*
+ * <TransitionsGroup Id="">
+ * <Transition>
+ * <To/>
+ * <Transition>
+ * <AbsoluteDateTransition/>
+ * <RecurringDayTransition/>
+ * <RecurringDateTransition/>
+ * </TransitionsGroup>
+ */
+typedef struct {
+ gchar *id;
+ EEwsCalendarTo *transition;
+ GSList *absolute_date_transitions; /* EEwsCalendarAbsoluteDateTransition */
+ GSList *recurring_day_transitions; /* EEwsCalendarRecurringDayTransition */
+ GSList *recurring_date_transitions; /* EEwsCalendarRecurringDateTransition */
+} EEwsCalendarTransitionsGroup;
+
+/*
+ * <Transitions Id="">
+ * <Transition>
+ * <To/>
+ * <Transition>
+ * <AbsoluteDateTransition/>
+ * <RecurringDayTransition/>
+ * <RecurringDateTransition/>
+ * </Transitions>
+ */
+typedef struct {
+ EEwsCalendarTo *transition;
+ GSList *absolute_date_transitions; /* EEwsCalendarAbsoluteDateTransition */
+ GSList *recurring_day_transitions; /* EEwsCalendarRecurringDayTransition */
+ GSList *recurring_date_transitions; /* EEwsCalendarRecurringDateTransition */
+} EEwsCalendarTransitions;
+
+/*
+ * <TimeZoneDefinition Id="" Name="">
+ * <Periods>
+ * <Period/>
+ * </Periods>
+ * <TransitionsGroups>
+ * <TransitionsGroup/>
+ * </TransitionsGroups>
+ * <Transitions/>
+ * </TimeZoneDefinition>
+ */
+typedef struct {
+ gchar *name;
+ gchar *id;
+ GSList *periods; /* EEwsCalendarPeriod */
+ GSList *transitions_groups; /* EEwsCalendarTrasitionsGroup */
+ EEwsCalendarTransitions *transitions;
+} EEwsCalendarTimeZoneDefinition;
+
+EEwsCalendarTo *
+ e_ews_calendar_to_new (void);
+void e_ews_calendar_to_free (EEwsCalendarTo *to);
+
+EEwsCalendarAbsoluteDateTransition *
+ e_ews_calendar_absolute_date_transition_new
+ (void);
+void e_ews_calendar_absolute_date_transition_free
+ (EEwsCalendarAbsoluteDateTransition *adt);
+
+EEwsCalendarRecurringDayTransition *
+ e_ews_calendar_recurring_day_transition_new
+ (void);
+void e_ews_calendar_recurring_day_transition_free
+ (EEwsCalendarRecurringDayTransition *rdayt);
+
+EEwsCalendarRecurringDateTransition *
+ e_ews_calendar_recurring_date_transition_new
+ (void);
+void e_ews_calendar_recurring_date_transition_free
+ (EEwsCalendarRecurringDateTransition *rdatet);
+
+EEwsCalendarPeriod *
+ e_ews_calendar_period_new (void);
+void e_ews_calendar_period_free (EEwsCalendarPeriod *period);
+
+EEwsCalendarTransitionsGroup *
+ e_ews_calendar_transitions_group_new
+ (void);
+void e_ews_calendar_transitions_group_free
+ (EEwsCalendarTransitionsGroup *tg);
+
+EEwsCalendarTransitions *
+ e_ews_calendar_transitions_new (void);
+void e_ews_calendar_transitions_free (EEwsCalendarTransitions *transitions);
+
+EEwsCalendarTimeZoneDefinition *
+ e_ews_calendar_time_zone_definition_new
+ (void);
+void e_ews_calendar_time_zone_definition_free
+ (EEwsCalendarTimeZoneDefinition *tzd);
+
EEwsNotificationEvent *
e_ews_notification_event_new (void);
void e_ews_notification_event_free (EEwsNotificationEvent *event);
@@ -1104,6 +1260,25 @@ void e_ews_connection_enable_notifications_sync
void e_ews_connection_disable_notifications_sync
(EEwsConnection *cnc,
guint subscription_key);
+void e_ews_connection_get_server_time_zones
+ (EEwsConnection *cnc,
+ gint pri,
+ GSList *msdn_locations,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean e_ews_connection_get_server_time_zones_finish
+ (EEwsConnection *cnc,
+ GAsyncResult *result,
+ GSList **tzds, /* EEwsCalendarTimeZoneDefinition */
+ GError **error);
+gboolean e_ews_connection_get_server_time_zones_sync
+ (EEwsConnection *cnc,
+ gint pri,
+ GSList *msdn_locations,
+ GSList **tzds, /* EEwsCalendarTimeZoneDefinition */
+ GCancellable *cancellable,
+ GError **error);
G_END_DECLS
diff --git a/src/server/e-ews-item.c b/src/server/e-ews-item.c
index c137dd0..e7aad64 100644
--- a/src/server/e-ews-item.c
+++ b/src/server/e-ews-item.c
@@ -1174,6 +1174,11 @@ e_ews_item_set_from_soap_parameter (EEwsItem *item,
priv->calendar_item_accept_id = g_new0 (EwsId, 1);
priv->calendar_item_accept_id->id = e_soap_parameter_get_property (subparam, "Id");
priv->calendar_item_accept_id->change_key = e_soap_parameter_get_property (subparam,
"ChangeKey");
+ } else if (!g_ascii_strcasecmp (name, "StartTimeZone")) {
+ if (priv->timezone != NULL)
+ g_free (priv->timezone);
+
+ priv->timezone = e_soap_parameter_get_property (subparam, "Id");
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]