[evolution-ews/wip/get_server_time_zones: 3/6] Bug #712179 - Cannot create calendar object: The property is deprecated for this version of Exchange



commit d7aca3dc00e2adb830925650d8ec45eb4d254e00
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 |  775 +++++++++++++++++++++++++++++++-
 src/calendar/e-cal-backend-ews-utils.h |   10 +-
 src/calendar/e-cal-backend-ews.c       |  183 ++++++--
 src/server/e-ews-connection.c          |  797 ++++++++++++++++++++++++++++++++
 src/server/e-ews-connection.h          |  175 +++++++
 src/server/e-ews-item.c                |    5 +
 6 files changed, 1898 insertions(+), 47 deletions(-)
---
diff --git a/src/calendar/e-cal-backend-ews-utils.c b/src/calendar/e-cal-backend-ews-utils.c
index 1add02c..601c73c 100644
--- a/src/calendar/e-cal-backend-ews-utils.c
+++ b/src/calendar/e-cal-backend-ews-utils.c
@@ -43,6 +43,634 @@
 #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_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       for (i = 0; i < (sizeof (ical_to_msdn_table) / sizeof (ical_to_msdn_table [0])); i++) {
+               g_hash_table_insert (
+                       ical_to_msdn,
+                       g_strdup (ical_to_msdn_table[i].from),
+                       g_strdup (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_full (g_str_hash, g_str_equal, g_free, g_free);
+
+       for (i = 0; i < (sizeof (msdn_to_ical_table) / sizeof (msdn_to_ical_table [0])); i++) {
+               g_hash_table_insert (
+                       msdn_to_ical,
+                       g_strdup (msdn_to_ical_table[i].from),
+                       g_strdup (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);
+}
+
+/*
  * Iterate over the icalcomponent properties and collect attendees
  */
 void
@@ -317,10 +945,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 +1129,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.
diff --git a/src/calendar/e-cal-backend-ews-utils.h b/src/calendar/e-cal-backend-ews-utils.h
index 6f265c0..8563749 100644
--- a/src/calendar/e-cal-backend-ews-utils.h
+++ b/src/calendar/e-cal-backend-ews-utils.h
@@ -37,7 +37,8 @@ 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 +48,13 @@ 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);
+
 G_END_DECLS
 
 #endif
diff --git a/src/calendar/e-cal-backend-ews.c b/src/calendar/e-cal-backend-ews.c
index 32aab8d..47abae6 100644
--- a/src/calendar/e-cal-backend-ews.c
+++ b/src/calendar/e-cal-backend-ews.c
@@ -98,6 +98,26 @@ struct _ECalBackendEwsPrivate {
 #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 +133,11 @@ 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);
 
@@ -1422,14 +1440,48 @@ convert_vevent_calcomp_to_xml (ESoapMessage *msg,
                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));
+       /* 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->cbews->priv->cnc, 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->cbews->priv->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->cbews->priv->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->cbews->priv->cnc,
+                               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->cbews->priv->default_zone));
+       }
 
        // end of "CalendarItem"
        e_soap_message_end_element (msg);
@@ -2324,20 +2376,67 @@ convert_vevent_component_to_updatexml (ESoapMessage *msg,
                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);
+       /* 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 (modify_data->cbews->priv->cnc, 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 (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);
+
+               if (e_ews_connection_get_server_time_zones_sync (
+                               modify_data->cbews->priv->cnc,
+                               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_timezone (msg, "MeetingTimeZone", (icaltimezone *)(dtstart.zone ? dtstart.zone : 
modify_data->cbews->priv->default_zone));
+               ewscal_set_meeting_timezone (
+                       msg,
+                       (icaltimezone *)(dtstart.zone ? dtstart.zone : 
modify_data->cbews->priv->default_zone));
                e_ews_message_end_set_item_field (msg);
        }
 
@@ -3609,9 +3708,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 +4001,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 +4081,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) {
@@ -4675,6 +4766,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 +4886,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/server/e-ews-connection.c b/src/server/e-ews-connection.c
index d549714..2016504 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;
+
+       if (success) {
+               to = e_ews_calendar_to_new ();
+               to->kind = kind;
+               to->value = value;
+       } else {
+               g_free (kind);
+               g_free (value);
+       }
+
+exit:
+       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]